帮助创建通用 WCF 服务调用程序 - 泛型、委托和 lambda

发布于 2024-11-03 08:57:59 字数 1180 浏览 8 评论 0原文

我正在尝试创建一个通用的 WCF 服务调用程序实用程序,但我对泛型、委托和 lambda 的了解让我在最后的障碍中失败了。

我希望能够封装调用 WCF Web 服务的身份验证和期望处理,以便我可以仅使用接口、请求和响应类来使用 Web 服务。

我不明白如何传递我想要执行的方法名称 - 我已经尝试过 Func<>路线,但我很困惑,因为我在下面实现的内容中遇到了递归错误。我也不想走硬编码字符串/反射路线 - 我希望这是一个强类型的类。

请帮忙!

谢谢

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

双手揣兜 2024-11-10 08:57:59

这是我的尝试。我的版本没有请求类型作为参数。我展示了我希望您如何使用它(您没有展示您计划如何调用您的方法,但我怀疑问题出在调用中,而不是方法本身)。

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

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;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文