2

The java version: I have the generic function as follows:

public <T, K> JsonEnvelop<T, K> readResponse(Class<T> t, Class<K> k)

And one class that implements InvocationHandler, in the invoke function, it will call the generic function just as follows:

JsonEnvelop<ResHeader, ?> response = conn.readResponse(ResHeader.class, method.getReturnType());

Now I want a C# version: Then I translate the generic function as below:

public JsonEnvelop<T, K> readResponse<T,K>()

And I want to call the function in the invoke body of a class that implements RealProxy, how can I achieve the same result as java version? The first generic type can be ResHeader, but the second one should be judged from methodCall, so how can I pass the parameter K?

public override IMessage Invoke(IMessage msg)
{
    var methodCall = msg as IMethodCallMessage;
    var response = conn.readResponse<ResHeader, Typge.Get(methodCall.TypeName)>(); 
    return new ReturnMessage(response.getBody(), null, 0, methodCall.LogicalCallContext, methodCall);
}

Another question is that is there any better way to translate the java code to C#?

Thanks very much!

Thanks Aron, the detail problem is:

I have different services, and for every service, it would provide several functions. Each function would send a request and get a response. The request and response would differ across functions and services. The design is to use the RealProxy to send the request and get the response. Here the "public JsonEnvelop readResponse(Class t, Class k)" is to get the response, and for different service and function, the T is the same as ResHeader, but the K is quite different and it rely on the parameters.

GetRealTimeQueryDataRequest request = new GetRealTimeQueryDataRequest();
GetRealTimeQueryDataResponse response=reportService.getRealTimeQueryData(request);

Take the above as example, it will call the invoke function in the realproxy implement class and the K should be the return type GetRealTimeQueryDataResponse

Tommy Tan
  • 95
  • 1
  • 12
  • Java to c# tools: http://codecall.net/2014/03/27/best-tools-to-convert-java-to-c-source-code/ – Jason W Aug 26 '15 at 02:21
  • What is your question? I don't understand what you are trying to achieve. What do you mean by "but the second one should be judged from methodCall"? It sounds like an XY problem here and you haven't given us what X is or what the entire problem is, or how you are achieving X, so I can't figure out how you want to fit Y into the solution. What is the entire class that inherits RealProxy doing? – Aron Aug 26 '15 at 02:36
  • Thanks for the tools recommendation. I tried it and it just simply translate some simple features, but could not deal with complex conditions such as generic/dynamic proxy – Tommy Tan Aug 26 '15 at 02:44

2 Answers2

0

C# does not support the "wildcard generics" as Java does. Typically to get around this, you leverage a feature in C# called "generic type inferencing" in which the type of the generic wrapping function is inferred when the method is called (there are many old SO answers comparing these).

A simple example here in C# is where you'd have a "?" in Java:

public T GetItem<T>(ICollection<T> input, int n) {
    return input.ElementAt(n);
}
var items = new List<int>() { 1, 2, 3 };
int secondItem = GetItem(input, 2); // int is inferred  based on generic type of collection item

For your example, you would likely need to re-work the method signature to be able to provide enough context for .NET to infer the generic type for your Invoke method.

Since your specific example only utilizes IMessage as the parameter and return object, generic type inferencing can't directly help here, and as stated above, there is no direct translation of this code into C# due to lack of support for generic wildcards. You'll have to explore other workarounds such as being more explicit than just IMessage to give enough context for the type inference to work or utilize other data types to rewrite the code (dynamic, dictionary, etc).

Jason W
  • 13,026
  • 3
  • 31
  • 62
0

The way to implement your specific problem is to define the request/response in your interface.

public interface IRequest<TResponse>
{

}

public class GetRealTimeQueryDataRequest : IRequest<GetRealTimeQueryDataResponse> {}

From there you can get use .GetType().GetInterfaces() to get IRequest<GetRealTimeQueryDataResponse> by filtering on "is typeof(IRequest<>)". Then you just need to get the generic type parameter of IRequest<GetRealTimeQueryDataResponse>.

However, this seems pretty strange way to implement this, as it is much simplier to use Dependency Injection and just get the Service that implements IHandle<GetRealTimeQueryDataRequest>. That way you don't need to use dynamics.

Aron
  • 15,464
  • 3
  • 31
  • 64