I'm trying to create a generic WCF service invoker utility but my knowledge of generics, delegates and lambda is failing me at the final hurdle.
I want to be able to encapsulate the authentication and expection handling of calling my WCF web services so that I can consume the web service with just the Interface, request and response classes to hand.
I don't understand how I can pass in the method name I want to execute - I have tried the Func<> route but am getting confused as I get a recursion error with what I have implemented below. I would prefer to not go down the hard coded string / reflection route either - I want this to be a strongly-typed class.
Please help!
Thank you
public static TResponse Invoke<TService, TRequest, TResponse>(TRequest request, Func<TService, TRequest, TResponse> methodToExecute, string endpointConfigurationName) where TResponse : class
{
ChannelFactory<TService> channel = new ChannelFactory<TService>(endpointConfigurationName);
// attach auth credentials
channel.Credentials.UserName.UserName = "myUserName";
channel.Credentials.UserName.Password = "myPassword";
// create a proxy for the channel
TService proxy = channel.CreateChannel();
TResponse response;
try
{
response = methodToExecute(proxy, request);
channel.Close();
}
catch
{
// abort or close in a fail-safe manner
if (channel.State == CommunicationState.Faulted)
{
channel.Abort();
}
else
{
channel.Close();
}
throw;
}
return response;
}
Here's my try. My version doesn't have the request type as a parameter. I show how I expect you to use it (you didn't show how you planned to invoke yours, but I suspect that the problem was in the invocation, not the method itself).
private class Response {}
private interface IService
{
Response MyMethod(object i);
}
public static void Foo()
{
object request = 1;
Response response = Invoke((IService service) => service.MyMethod(request), "endpoint");
}
public static TResponse Invoke<TService, TResponse>(Func<TService, TResponse> methodToExecute, string endpointConfigurationName) where TResponse : class
{
ChannelFactory<TService> channel = new ChannelFactory<TService>(endpointConfigurationName);
// attach auth credentials
channel.Credentials.UserName.UserName = "myUserName";
channel.Credentials.UserName.Password = "myPassword";
// create a proxy for the channel
TService proxy = channel.CreateChannel();
TResponse response;
try
{
response = methodToExecute(proxy);
channel.Close();
}
catch
{
// abort or close in a fail-safe manner
if (channel.State == CommunicationState.Faulted)
{
channel.Abort();
}
else
{
channel.Close();
}
throw;
}
return response;
}