.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服务端的代码结构如下:

采用标准的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项目。

客户端项目结构如下:

客户端配置文件如下:

<?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();
        }
    }

启动运行结果如下:

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

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

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

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

时间: 2024-10-28 09:21:27

.NET Core调用WCF的最佳实践的相关文章

.NET Core 调用WCF 服务

.NET Core 和ASP.NET Core 已经可以调用WCF 服务. 环境要求: VS2015 Update 2 +VS2015 Tooling + .NET Core SDK 下载地址: https://www.microsoft.com/net/core 已经安装可以忽略. 安装扩展 打开VS2015 在 工具->扩展和更新 联机中搜索 WCF Connected Service 然后下载安装.安装完成后重启VS2015. 创建WCF服务 新建一个wcf 服务,里面添加一些方法. IN

[转]ASP.NET Core Web API 最佳实践指南

原文地址: ASP.NET-Core-Web-API-Best-Practices-Guide 转自 介绍# 当我们编写一个项目的时候,我们的主要目标是使它能如期运行,并尽可能地满足所有用户需求. 但是,你难道不认为创建一个能正常工作的项目还不够吗?同时这个项目不应该也是可维护和可读的吗? 事实证明,我们需要把更多的关注点放到我们项目的可读性和可维护性上.这背后的主要原因是我们或许不是这个项目的唯一编写者.一旦我们完成后,其他人也极有可能会加入到这里面来. 因此,我们应该把关注点放到哪里呢? 在

Cocos2d-x下Lua调用自定义C++类和函数的最佳实践

原文地址:http://segmentfault.com/a/1190000000631630 关于cocos2d-x下Lua调用C++的文档看了不少,但没有一篇真正把这事给讲明白了,我自己也是个初学者,摸索了半天,总结如下: cocos2d-x下Lua调用C++这事之所以看起来这么复杂.网上所有的文档都没讲清楚,是因为存在5个层面的知识点: 1.在纯C环境下,把C函数注册进Lua环境,理解Lua和C之间可以互相调用的本质2.在cocos2d-x项目里,把纯C函数注册进Lua环境,理解cocos

【转】Cocos2d-x下Lua调用自定义C++类和函数的最佳实践

转自:http://segmentfault.com/blog/hongliang/1190000000631630 关于cocos2d-x下Lua调用C++的文档看了不少,但没有一篇真正把这事给讲明白了,我自己也是个初学者,摸索了半天,总结如下: cocos2d-x下Lua调用C++这事之所以看起来这么复杂.网上所有的文档都没讲清楚,是因为存在5个层面的知识点: 1.在纯C环境下,把C函数注册进Lua环境,理解Lua和C之间可以互相调用的本质 2.在cocos2d-x项目里,把纯C函数注册进L

Javascript模块化编程(一)模块的写法最佳实践六、输入全局变量 独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互。 为了在模块内部调用全局变量,必须显式地将其他变量输入模块。

Javascript模块化编程,已经成为一个迫切的需求.理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块但是,Javascript不是一种模块化编程语言,它不支持类class,更遑论模块module了 随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂.网页越来越像桌面程序,需要一个团队分工协作.进度管理.单元测试等等......开发者不得不使用软件工程的方法,管理网页的业务逻辑. Javascript模块化编程,已

Cocos2d-x下Lua调用自定义C++类和函数的最佳实践 -- 转

原地址: http://blog.segmentfault.com/hongliang/1190000000631630 Cocos2d-x下Lua调用自定义C++类和函数的最佳实践 关于cocos2d-x下Lua调用C++的文档看了不少,但没有一篇真正把这事给讲明白了,我自己也是个初学者,摸索了半天,总结如下: cocos2d-x下Lua调用C++这事之所以看起来这么复杂.网上所有的文档都没讲清楚,是因为存在5个层面的知识点: 1.在纯C环境下,把C函数注册进Lua环境,理解Lua和C之间可以

Dependency injection in .NET Core的最佳实践

我们知道依赖注入(DI)是一种实现对象及其协作者或依赖关系之间松散耦合的技术. ASP.NET Core包含一个简单的内建容器来支持构造器注入. 我们试图将DI的最佳实践带到.NET Core应用程序中,这表现在以下方面: 构造器注入 注册组件 DI in testing 构造器注入 我们可以通过方法注入.属性注入.构造器注入的方式来注入具体的实例,一般来说构造器注入的方式被认为是最好的方式,所以在应用程序中将使用构造器注入,请避免使用别的注入方式.一个构造器注入的例子如: public cla

ASP.NET Core 依赖注入最佳实践——提示与技巧

在这篇文章,我将分享一些在ASP.NET Core程序中使用依赖注入的个人经验和建议.这些原则背后的动机如下: 高效地设计服务和它们的依赖. 预防多线程问题. 预防内存泄漏. 预防潜在的BUG. 这篇文章假设你已经基本熟悉依赖注入和ASP.NET Core.如果不是,则先阅读文章: 在ASP.NET Core中使用依赖注入 基础 构造函数注入 构造函数注入常用于在服务构建上定义和获取服务依赖.例如: 1 public class ProductService 2 { 3 private read

.NET Core 2.1中的HttpClientFactory最佳实践

ASP.NET Core 2.1中出现一个新的HttpClientFactory功能, 它有助于解决开发人员在使用HttpClient实例从其应用程序发出外部Web请求时可能遇到的一些常见问题. 介绍 在.NETCore平台的2.1新增了HttpClientFactory,虽然HttpClient这个类实现了disposable,但使用它的时候用声明using包装块的方式通常不是最好的选择.处理HttpClient,底层socket套接字不会立即释放.该HttpClient类是专为多个请求重复使