.NET Core调用WCF的最佳实践

现在.NET Core貌似很火,与其他.NET开发者交流不说上几句.NET Core都感觉自己落伍了一样。但是冷静背后我们要也看到.NET Core目前还有太多不足,别的不多说,与自家的服务框架WCF集成起来就不咋地,从最初不支持,到现在有个笨笨咔咔的Web Service Reference Provider,生成的代理类简直不堪入目,还特别的慢。所以本人本着为将来框架的兼容性做准备,就着手研究了下能不能不通过代理类访问WCF,好在微软开源了一部分WCF代码。

WCF的开发者一定很熟悉,WCF的所有配置都是可以通过代码和配置文件两种方式,而大多数开发者都会选择配置文件,但是从.NET Core开始,微软干掉了Web/App.config,不知道别人怎么样,反正我是非常之不习惯。干掉Web/App.config的后果,就是开源支持.NET Core的那部分Client Side没有配置文件的支持,翻看源码后发现,只要是读取配置文件的地方,都是这样的代码 —— PlatformNotSupported。

protected void InitializeEndpoint(string configurationName, EndpointAddress address)

{

            _serviceEndpoint = this.CreateDescription();


            ServiceEndpoint serviceEndpointFromConfig = null;


            // Project N and K do not support System.Configuration, but this method is part of Windows Store contract.

            // The configurationName==null path occurs in normal use.

            if (configurationName != null)

            {

                throw ExceptionHelper.PlatformNotSupported();

                // serviceEndpointFromConfig = ConfigLoader.LookupEndpoint(configurationName, address, this.serviceEndpoint.Contract);

       }

}

但是好在微软又推出了System.Configuration.ConfigurationManager的NuGet包,所以本人仿照WCF原生的配置文件,自己实现一套配置,经过两个晚上的战斗,已经成功。好了,废话不多说,上代码了。

先看看最终的效果是什么样的,WCF服务端的代码结构如下:

640?wx_fmt=png

采用标准的WCF分层方式,用控制台做宿主,其中IAppService项目版本为.NET Standard 2.0,每个终结点同时使用BasicHttpBinding与NetTcpBinding双重绑定,配置文件如下:

<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <!--WCF配置-->

  <system.serviceModel>

    <!--WCF服务配置,手动增加service节点-->

    <services>

      <!--产品服务配置-->

      <service behaviorConfiguration="DefaultBehavior" name="WCF.AppService.Implements.ProductService">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8098/Hosts/ProductService.svc" />

            <add baseAddress="net.tcp://localhost:8099/Hosts/ProductService.svc" />

          </baseAddresses>

        </host>

        <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="WCF.IAppService.Interfaces.IProductService" />

        <endpoint binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WCF.IAppService.Interfaces.IProductService" />

      </service>

      <!--订单服务配置-->

      <service behaviorConfiguration="DefaultBehavior" name="WCF.AppService.Implements.OrderService">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8098/Hosts/OrderService.svc" />

            <add baseAddress="net.tcp://localhost:8099/Hosts/OrderService.svc" />

          </baseAddresses>

        </host>

        <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="WCF.IAppService.Interfaces.IOrderService" />

        <endpoint binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WCF.IAppService.Interfaces.IOrderService" />

      </service>

      <!--集成服务配置-->

      <service behaviorConfiguration="DefaultBehavior" name="WCF.AppService.Implements.IntegrationService">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8098/Hosts/IntegrationService.svc" />

            <add baseAddress="net.tcp://localhost:8099/Hosts/IntegrationService.svc" />

          </baseAddresses>

        </host>

        <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="WCF.IAppService.Interfaces.IIntegrationService" />

        <endpoint binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WCF.IAppService.Interfaces.IIntegrationService" />

      </service>

    </services>

    <!--WCF行为配置,配置好无需修改-->

    <behaviors>

      <serviceBehaviors>

        <behavior name="DefaultBehavior">

          <!--是否允许get请求访问-->

          <serviceMetadata httpGetEnabled="true" />

          <!--允许从请求消息头中检索元数据地址信息-->

          <useRequestHeadersForMetadataAddress />

          <!--是否显示异常信息-->

          <serviceDebug includeExceptionDetailInFaults="true" />

          <!--最大序列化的对象个数-->

          <dataContractSerializer maxItemsInObjectGraph="2147483647" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

    <!--WCF绑定配置,配置好无需修改-->

    <bindings>

      <netTcpBinding>

        <binding name="tcpBinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" />

      </netTcpBinding>

      <basicHttpBinding>

        <binding name="basicBinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" />

      </basicHttpBinding>

    </bindings>

    <!--WCF多宿主绑定配置-->

    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />

  </system.serviceModel>

</configuration>

运行测试没问题,服务端不多说,重点是客户端,因为IAppService是.NET Standard 2.0的类库版本,所以.NET Core客户端是可以正常引用的,新建.NET Core控制台,并引用上述IAppService项目。

客户端项目结构如下:

640?wx_fmt=png

客户端配置文件如下:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <configSections>

    <!--WCF配置节点-->

    <section name="system.serviceModel" type="System.ServiceModel.ServiceModelSection, System.ServiceModel.Toolkits" />

  </configSections>


  <!--WCF配置-->

  <system.serviceModel>

    <!--WCF客户端配置,手动增加endpoint节点-->

    <client>

      <!--商品服务契约配置-->

      <endpoint address="net.tcp://localhost:8099/Hosts/ProductService.svc" binding="netTcpBinding" contract="WCF.IAppService.Interfaces.IProductService" name="WCF.IAppService.Interfaces.IProductService">

        <headerProvider type="WCF.Core.Client.HeaderProviders.MyHeaderProvider" assembly="WCF.Core.Client"/>

      </endpoint>

      <!--订单服务契约配置-->

      <endpoint address="net.tcp://localhost:8099/Hosts/OrderService.svc" binding="netTcpBinding" contract="WCF.IAppService.Interfaces.IOrderService" name="WCF.IAppService.Interfaces.IOrderService" />

      <!--集成服务契约配置-->

      <endpoint address="net.tcp://localhost:8099/Hosts/IntegrationService.svc" binding="netTcpBinding" contract="WCF.IAppService.Interfaces.IIntegrationService" name="WCF.IAppService.Interfaces.IIntegrationService" />

    </client>

  </system.serviceModel>

</configuration>

Main方法中代码如下:

class Program

    {

        static void Main(string[] args)

        {

            //初始化容器

            IContainer container = InitContainer();


            //调用

            IProductService productService = container.Resolve<IProductService>();

            string products = productService.GetProducts();


            Console.WriteLine(products);


            container.Dispose();

            Console.ReadKey();

        }


        static IContainer InitContainer()

        {

            ContainerBuilder builder = new ContainerBuilder();

            Assembly wcfInterfaceAssembly = Assembly.Load("WCF.IAppService");


            //获取WCF接口类型集

            IEnumerable<Type> types = wcfInterfaceAssembly.GetTypes().Where(type => type.IsInterface);


            //获取服务代理泛型类型

            Type proxyGenericType = typeof(ServiceProxy<>);


            //注册WCF接口

            foreach (Type type in types)

            {

                Type proxyType = proxyGenericType.MakeGenericType(type);

                PropertyInfo propChannel = proxyType.GetProperty(ServiceProxy.ChannelPropertyName, type);


                builder.RegisterType(proxyType).OnRelease(proxy => ((IDisposable)proxy).Dispose());

                builder.Register(container => propChannel.GetValue(container.Resolve(proxyType))).

                    As(type).

                    OnRelease(channel => channel.CloseChannel());

            }


            return builder.Build();

        }

    }

启动运行结果如下:

640?wx_fmt=png

怎么样?是不是觉得很清爽?如果你有兴趣,可以到我的Git看全部源码,地址如下:

https://gitee.com/lishilei0523/WCF-DotNetCore

Ps:因为微软公开的WCF类库本身就不完善,所以我也没法提供全部的功能,本人所作调用方式目前支持BasicHttpBinding和NetTcpBinding,并且包含消息头支持。如果你觉得代码对你有帮助,麻烦点个Star,不胜感激。

欢迎进入我的码云 https://gitee.com/lishilei0523


原文地址:http://www.cnblogs.com/lishilei0523/p/8886483.html


 
 

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值