Search code examples
.netwcfproxyproxy-classes

Help creating a generic WCF service invoker - generics, delegates and lambda


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;
}

Solution

  • 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;
        }