• 让WCF客户端的“调用”成为一种“享受”


    推荐WCF客户端实现:享受无止境 - 改进版WCF Client

    刚开始使用WCF时,总是在using中进行调用,比如:

    using (CnblogsWcfClient client = new CnblogsWcfClient())
    {
    client.Say("Hello, cnblogs.com!");
    }

    后来发现,这是微软的一个“骗局”,当时我写了篇博客“不要在using语句中调用WCF服务”。

    从此改为这样调用:

    CnblogsWcfClient client = new CnblogsWcfClient();
    client.Say("Hello, cnblogs.com!");
    try
    {
    client.Close();
    }
    catch
    {
    client.Abort();
    }

    每当写到这样的代码,心理总是有些不舒服。经过近10个月这样的不舒服之后,再也无法忍受。。。

    于是,今天决定解决这个问题。。。

    What is the best workaround for the WCF client `using` block issue? 找到 Practical Functional C# - Part II,发现了解决之道,但其中提供的代码不完整,经过几个小时的摸索,终于找到满意的解决方法。

    让WCF客户端的调用成为“享受”的代码如下:

    应用程序中调用代码:

    调用代码一

    //IUserService就是WCF的ServiceContract,是客户端自动生成的代理类
    WcfClient.UseService((IUserService userService) => (userService.GetUser(userId)));

    调用代码二:

    WcfClient.UseService<IUserService , User>(s => s.GetUser(userId));

    WcfClient实现代码一(该代码只支持有返回值的WCF服务,推荐第二种实现代码):

    public class WcfClient
    {
    public static TReturn UseService<TChannel, TReturn>(Func<TChannel, TReturn> func)
    {
    var chanFactory = new ChannelFactory<TChannel>("*");
    TChannel channel = chanFactory.CreateChannel();
    ((IClientChannel)channel).Open(); 
    TReturn result = func(channel);
            try
    {
    ((IClientChannel)channel).Close();
    }
    catch
    {
    ((IClientChannel)channel).Abort();
    }
    return result;
    }
    }

    解决这个问题的主要时间花在找到上面代码中的那个星号,星号对应的参数名是endpointConfigurationName。

    开始时困扰于如何给endpointConfigurationName参数传值。后来,研究了一下自动生成的代理类,也没有与endpointConfigurationName相关的信息,只是继承自System.ServiceModel.ClientBase<T>。然后,通过ILSPy反编译ClientBase<T>的代码,找到了这个星号,见下图:

    小结

    也许还有更“享受”的调用WCF客户端方法,但是我觉得至少比以前的方法用起来更舒服。解决问题之后,最好的庆祝方式就是写一篇博客。分享的不仅仅是解决方法,还有解决问题之后的那种兴奋!

    补充

    还有一种WcfClient实现方法(即支持有返回值的WCF服务,也支持无返回值的WCF服务),代码如下:

    public static void UseService<TChannel>(Action<TChannel> action)
    {
    var chanFactory = new ChannelFactory<TChannel>("*");
    TChannel channel = chanFactory.CreateChannel();
    ((IClientChannel)channel).Open();
    action(channel);
    try
    {
    ((IClientChannel)channel).Close();
    }
    catch
    {
    ((IClientChannel)channel).Abort();
    }
    }

    WCF客户端调用示例代码:

    WcfClient.UseService<IFeedService>(s => s.BeginCreate(feed, null, null));
  • 相关阅读:
    (转)android
    (转)Eclipse 扩大内存
    (转)setTextColor()的参数设置方式
    RelativeLayout里的gravity不能居中的解决方法
    hdu1010 Tempter of the Bone
    ubuntu系统下如何禁用笔记本触摸板
    十滴水,半成品,大多数关卡可以过去,不过也有几个过不去,仍在调试中,不断更新
    HDU1007 TLE代码和AC代码对比
    hdu1013
    1005 矩阵快速幂
  • 原文地址:https://www.cnblogs.com/dudu/p/wcf_client_no_using_call.html
Copyright © 2020-2023  润新知