现在.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。

  1. protected void InitializeEndpoint(string configurationName, EndpointAddress address)
  2. {
  3. _serviceEndpoint = this.CreateDescription();
  4.  
  5. ServiceEndpoint serviceEndpointFromConfig = null;
  6.  
  7. // Project N and K do not support System.Configuration, but this method is part of Windows Store contract.
  8. // The configurationName==null path occurs in normal use.
  9. if (configurationName != null)
  10. {
  11. throw ExceptionHelper.PlatformNotSupported();
  12. // serviceEndpointFromConfig = ConfigLoader.LookupEndpoint(configurationName, address, this.serviceEndpoint.Contract);
           }
    }

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

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

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

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <configuration>
  3. <!--WCF配置-->
  4. <system.serviceModel>
  5. <!--WCF服务配置,手动增加service节点-->
  6. <services>
  7. <!--产品服务配置-->
  8. <service behaviorConfiguration="DefaultBehavior" name="WCF.AppService.Implements.ProductService">
  9. <host>
  10. <baseAddresses>
  11. <add baseAddress="http://localhost:8098/Hosts/ProductService.svc" />
  12. <add baseAddress="net.tcp://localhost:8099/Hosts/ProductService.svc" />
  13. </baseAddresses>
  14. </host>
  15. <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="WCF.IAppService.Interfaces.IProductService" />
  16. <endpoint binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WCF.IAppService.Interfaces.IProductService" />
  17. </service>
  18. <!--订单服务配置-->
  19. <service behaviorConfiguration="DefaultBehavior" name="WCF.AppService.Implements.OrderService">
  20. <host>
  21. <baseAddresses>
  22. <add baseAddress="http://localhost:8098/Hosts/OrderService.svc" />
  23. <add baseAddress="net.tcp://localhost:8099/Hosts/OrderService.svc" />
  24. </baseAddresses>
  25. </host>
  26. <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="WCF.IAppService.Interfaces.IOrderService" />
  27. <endpoint binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WCF.IAppService.Interfaces.IOrderService" />
  28. </service>
  29. <!--集成服务配置-->
  30. <service behaviorConfiguration="DefaultBehavior" name="WCF.AppService.Implements.IntegrationService">
  31. <host>
  32. <baseAddresses>
  33. <add baseAddress="http://localhost:8098/Hosts/IntegrationService.svc" />
  34. <add baseAddress="net.tcp://localhost:8099/Hosts/IntegrationService.svc" />
  35. </baseAddresses>
  36. </host>
  37. <endpoint binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="WCF.IAppService.Interfaces.IIntegrationService" />
  38. <endpoint binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WCF.IAppService.Interfaces.IIntegrationService" />
  39. </service>
  40. </services>
  41. <!--WCF行为配置,配置好无需修改-->
  42. <behaviors>
  43. <serviceBehaviors>
  44. <behavior name="DefaultBehavior">
  45. <!--是否允许get请求访问-->
  46. <serviceMetadata httpGetEnabled="true" />
  47. <!--允许从请求消息头中检索元数据地址信息-->
  48. <useRequestHeadersForMetadataAddress />
  49. <!--是否显示异常信息-->
  50. <serviceDebug includeExceptionDetailInFaults="true" />
  51. <!--最大序列化的对象个数-->
  52. <dataContractSerializer maxItemsInObjectGraph="2147483647" />
  53. </behavior>
  54. </serviceBehaviors>
  55. </behaviors>
  56. <!--WCF绑定配置,配置好无需修改-->
  57. <bindings>
  58. <netTcpBinding>
  59. <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" />
  60. </netTcpBinding>
  61. <basicHttpBinding>
  62. <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" />
  63. </basicHttpBinding>
  64. </bindings>
  65. <!--WCF多宿主绑定配置-->
  66. <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  67. </system.serviceModel>
  68. </configuration>

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

客户端项目结构如下:

客户端配置文件如下:

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <configuration>
  3. <configSections>
  4. <!--WCF配置节点-->
  5. <section name="system.serviceModel" type="System.ServiceModel.ServiceModelSection, System.ServiceModel.Toolkits" />
  6. </configSections>
  7.  
  8. <!--WCF配置-->
  9. <system.serviceModel>
  10. <!--WCF客户端配置,手动增加endpoint节点-->
  11. <client>
  12. <!--商品服务契约配置-->
  13. <endpoint address="net.tcp://localhost:8099/Hosts/ProductService.svc" binding="netTcpBinding" contract="WCF.IAppService.Interfaces.IProductService" name="WCF.IAppService.Interfaces.IProductService">
  14. <headerProvider type="WCF.Core.Client.HeaderProviders.MyHeaderProvider" assembly="WCF.Core.Client"/>
  15. </endpoint>
  16. <!--订单服务契约配置-->
  17. <endpoint address="net.tcp://localhost:8099/Hosts/OrderService.svc" binding="netTcpBinding" contract="WCF.IAppService.Interfaces.IOrderService" name="WCF.IAppService.Interfaces.IOrderService" />
  18. <!--集成服务契约配置-->
  19. <endpoint address="net.tcp://localhost:8099/Hosts/IntegrationService.svc" binding="netTcpBinding" contract="WCF.IAppService.Interfaces.IIntegrationService" name="WCF.IAppService.Interfaces.IIntegrationService" />
  20. </client>
  21. </system.serviceModel>
  22. </configuration>

Main方法中代码如下:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. //初始化容器
  6. IContainer container = InitContainer();
  7.  
  8. //调用
  9. IProductService productService = container.Resolve<IProductService>();
  10. string products = productService.GetProducts();
  11.  
  12. Console.WriteLine(products);
  13.  
  14. container.Dispose();
  15. Console.ReadKey();
  16. }
  17.  
  18. static IContainer InitContainer()
  19. {
  20. ContainerBuilder builder = new ContainerBuilder();
  21. Assembly wcfInterfaceAssembly = Assembly.Load("WCF.IAppService");
  22.  
  23. //获取WCF接口类型集
  24. IEnumerable<Type> types = wcfInterfaceAssembly.GetTypes().Where(type => type.IsInterface);
  25.  
  26. //获取服务代理泛型类型
  27. Type proxyGenericType = typeof(ServiceProxy<>);
  28.  
  29. //注册WCF接口
  30. foreach (Type type in types)
  31. {
  32. Type proxyType = proxyGenericType.MakeGenericType(type);
  33. PropertyInfo propChannel = proxyType.GetProperty(ServiceProxy.ChannelPropertyName, type);
  34.  
  35. builder.RegisterType(proxyType).OnRelease(proxy => ((IDisposable)proxy).Dispose());
  36. builder.Register(container => propChannel.GetValue(container.Resolve(proxyType))).
  37. As(type).
  38. OnRelease(channel => channel.CloseChannel());
  39. }
  40.  
  41. return builder.Build();
  42. }
  43. }

启动运行结果如下:

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

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

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

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

  1. .NET Core 调用WCF 服务

    .NET Core 和ASP.NET Core 已经可以调用WCF 服务. 环境要求: VS2015 Update 2 +VS2015 Tooling + .NET Core SDK 下载地址: ht ...

  2. EntityFramework Core进行读写分离最佳实践方式,了解一下(二)?

    前言 写过上一篇关于EF Core中读写分离最佳实践方式后,虽然在一定程度上改善了问题,但是在评论中有的指出更换到从数据库,那么接下来要进行插入此时又要切换到主数据库,同时有的指出是否可以进行底层无感 ...

  3. EntityFramework Core进行读写分离最佳实践方式,了解一下(一)?

    前言 本来打算写ASP.NET Core MVC基础系列内容,看到有园友提出如何实现读写分离,这个问题提的好,大多数情况下,对于园友在评论中提出的问题,如果是值得深究或者大多数同行比较关注的问题我都会 ...

  4. WCF+AJAX最佳实践

    本文是基于Frank Xu的一个webcast上的串并总结,图片等都截至视频,谨致谢. 路线图 什么是WCF Windows Communication Foundation是MS为构建面向服务的应用 ...

  5. POST调用WCF方法-项目实践

    做即时通信项目时,需要与OA系统对接接口,主要目标是实现在OA里进行一项事项,通过调用我们的接口,即时通知过来,并弹出消息框提示一下.我们的即时通信使用的WCF服务进行通信,在客户端调用通信时,用的就 ...

  6. 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生

    [转].NET(C#):浅谈程序集清单资源和RESX资源   目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...

  7. ASP.NET Core Web API 最佳实践指南

    原文地址: ASP.NET-Core-Web-API-Best-Practices-Guide 介绍 当我们编写一个项目的时候,我们的主要目标是使它能如期运行,并尽可能地满足所有用户需求. 但是,你难 ...

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

    原文地址: ASP.NET-Core-Web-API-Best-Practices-Guide 转自 介绍# 当我们编写一个项目的时候,我们的主要目标是使它能如期运行,并尽可能地满足所有用户需求. 但 ...

  9. ASP.NET Core 依赖注入最佳实践与技巧

    ASP.NET Core 依赖注入最佳实践与技巧 原文地址:https://medium.com/volosoft/asp-net-core-dependency-injection-best-pra ...

随机推荐

  1. JS 位数不够自动左补0

    var mycode = "11"; mycode = (Array(4).join(0) + parseInt(mycode)).slice(-4);//0011 mycode1 ...

  2. ArrayList原理(一)

    需要使用到动态数组的时候用的最多的就是ArrayList了,底层其实是Object数组,以下demo基于JDK1.8: List<Integer> list  = new ArrayLis ...

  3. VML元素的相关资料

    虽然VML已经过气了,但有时我还不得不使用它,下面是我收集或研究得到的一些东西. 判定一个元素是否为VML元素 function isVML(el) { if (el && el.no ...

  4. Node.js究竟是什么?

    来源:https://www.ibm.com/developerworks/cn/opensource/os-nodejs/index.html?ca=drs#ibm-pcon   Node 旨在解决 ...

  5. Hello Vizhub

    VizHub.com 一.介绍 Vizhub是一个使用D3.js和svg进行数据可视化的教学练三位一体的平台. 并且可以把在线编辑的代码保存到网站中. 右上角可以使用github账号登录. 二.Get ...

  6. Unix高级编程Note1

    [Unix Notes] 1./etc/passwd 2.extern int errno; 3.限制, limit.h 4.文件原子操作:O_EXCL & O_CREAT 5.stat操作 ...

  7. S 合伙人

    [Public] ConnectString=host="siebel://10.10.0.46:2321/HC_CRM/SMObjMgr_chs ConnectUserName=SADMI ...

  8. JS 语法大全

    来源http://blog.csdn.net/newegg2009/article/details/6230582 js语法2008年03月19日 星期三 11:14一.js的数据类型和变量 Java ...

  9. Country Meow

    Country Meow 和这基本一样 https://www.cnblogs.com/Fighting-sh/p/9809518.html #include<iostream> #inc ...

  10. MFC The Screen Flickers When The Image Zoomed

    问题描述 当初写MFC也是不情愿的. 既然写了,遇到一些问题. 解决也废了一切功夫.所以简单的记录一下. 这个问题,也就是使用MFC显示图像的时候, 放缩图像的过程中, 图像会一闪一闪的. 这个问题的 ...