WCF透明代理类,动态调用,支持async/await
我们希望WCF客户端调用采用透明代理方式,不用添加服务引用,也不用Invoke的方式,通过ChannelFactory<>动态产生通道,实现服务接口进行调用,并且支持async/await,当然也不用在Config中配置serviceModel。
服务端代码:
- [ServiceContract]
- public interface IGameService
- {
- [OperationContract]
- Task DoWorkAsync(string arg);
- [OperationContract]
- void DoWork(string arg);
- }
- public class GameService : IGameService
- {
- public async Task<string> DoWorkAsync(string arg)
- {
- return await Task.FromResult($"Hello {arg}, I am the GameService.");
- }
- public string DoWork(string arg)
- {
- return $"Hello {arg}, I am the GameService.";
- }
- }
- [ServiceContract]
- public interface IPlayerService
- {
- [OperationContract]
- Task<string> DoWorkAsync(string arg);
- [OperationContract]
- string DoWork(string arg);
- }
- public class PlayerService : IPlayerService
- {
- public async Task<string> DoWorkAsync(string arg)
- {
- return await Task.FromResult($"Hello {arg}, I am the PlayerService.");
- }
- public async string DoWork(string arg)
- {
- return $"Hello {arg}, I am the PlayerService.";
- }
- }
代理类
动态创建服务对象,ChannelFactory<T>的运用,一个抽象类
- namespace Wettery.Infrastructure.Wcf
- {
- public enum WcfBindingType
- {
- BasicHttpBinding,
- NetNamedPipeBinding,
- NetPeerTcpBinding,
- NetTcpBinding,
- WebHttpBinding,
- WSDualHttpBinding,
- WSFederationHttpBinding,
- WSHttpBinding
- }
- public abstract class WcfChannelClient<TChannel> : IDisposable
- {
- public abstract string ServiceUrl { get; }
- private Binding _binding;
- public virtual Binding Binding
- {
- get
- {
- if (_binding == null)
- _binding = CreateBinding(WcfBindingType.NetTcpBinding);
- return _binding;
- }
- }
- protected TChannel _channel;
- public TChannel Channel
- {
- get { return _channel; }
- }
- protected IClientChannel ClientChannel
- {
- get { return (IClientChannel)_channel; }
- }
- public WcfChannelClient()
- {
- if (string.IsNullOrEmpty(this.ServiceUrl)) throw new NotSupportedException("ServiceUrl is not overridden by derived classes.");
- var chanFactory = new ChannelFactory<TChannel>(this.Binding, this.ServiceUrl);
- _channel = chanFactory.CreateChannel();
- this.ClientChannel.Open();
- }
- protected virtual void Dispose(bool disposing)
- {
- if (disposing && this.ClientChannel != null)
- {
- try
- {
- this.ClientChannel.Close(TimeSpan.FromSeconds());
- }
- catch
- {
- this.ClientChannel.Abort();
- }
- }
- //TODO: free unmanaged resources
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- ~WcfChannelClient()
- {
- Dispose(false);
- }
- private static Binding CreateBinding(WcfBindingType binding)
- {
- Binding bindinginstance = null;
- if (binding == WcfBindingType.BasicHttpBinding)
- {
- BasicHttpBinding ws = new BasicHttpBinding();
- ws.MaxBufferSize = ;
- ws.MaxBufferPoolSize = ;
- ws.MaxReceivedMessageSize = ;
- ws.ReaderQuotas.MaxStringContentLength = ;
- ws.CloseTimeout = new TimeSpan(, , );
- ws.OpenTimeout = new TimeSpan(, , );
- ws.ReceiveTimeout = new TimeSpan(, , );
- ws.SendTimeout = new TimeSpan(, , );
- bindinginstance = ws;
- }
- else if (binding == WcfBindingType.NetNamedPipeBinding)
- {
- NetNamedPipeBinding ws = new NetNamedPipeBinding();
- ws.MaxReceivedMessageSize = ;
- bindinginstance = ws;
- }
- else if (binding == WcfBindingType.NetPeerTcpBinding)
- {
- //NetPeerTcpBinding ws = new NetPeerTcpBinding();
- //ws.MaxReceivedMessageSize = 65535000;
- //bindinginstance = ws;
- throw new NotImplementedException();
- }
- else if (binding == WcfBindingType.NetTcpBinding)
- {
- NetTcpBinding ws = new NetTcpBinding();
- ws.MaxReceivedMessageSize = ;
- ws.Security.Mode = SecurityMode.None;
- bindinginstance = ws;
- }
- else if (binding == WcfBindingType.WebHttpBinding)
- {
- WebHttpBinding ws = new WebHttpBinding(); //Restful style
- ws.MaxReceivedMessageSize = ;
- bindinginstance = ws;
- }
- else if (binding == WcfBindingType.WSDualHttpBinding)
- {
- WSDualHttpBinding ws = new WSDualHttpBinding();
- ws.MaxReceivedMessageSize = ;
- bindinginstance = ws;
- }
- else if (binding == WcfBindingType.WSFederationHttpBinding)
- {
- WSFederationHttpBinding ws = new WSFederationHttpBinding();
- ws.MaxReceivedMessageSize = ;
- bindinginstance = ws;
- }
- else if (binding == WcfBindingType.WSHttpBinding)
- {
- WSHttpBinding ws = new WSHttpBinding(SecurityMode.None);
- ws.MaxReceivedMessageSize = ;
- ws.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
- ws.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
- bindinginstance = ws;
- }
- return bindinginstance;
- }
- }
- }
针对每个WCF服务派生一个代理类,在其中重写ServiceUrl与Binding,ServiceUrl可以配置到Config中,Binding不重写默认采用NetTcpBinding
- public class GameServiceClient : WcfChannelClient<IGameService>
- {
- public override string ServiceUrl
- {
- get
- {
- return "net.tcp://localhost:21336/GameService.svc";
- }
- }
- }
- public class PlayerServiceClient : WcfChannelClient<IPlayerService>
- {
- public override string ServiceUrl
- {
- get
- {
- return "net.tcp://localhost:21336/PlayerService.svc";
- }
- }
- }
客户端调用
- using (var client = new GameServiceClient())
- {
- client.Channel.DoWork("thinkpig"); //无返回值
- await client.Channel.DoWorkAsync("thinkpig"); //无返回值异步
- }
- using (var client = new PlayerServiceClient())
- {
- var result = client.Channel.DoWork("thinkdog"); //有返回值
- result = await client.Channel.DoWorkAsync("thinkdog"); //有返回值异步
- }
关于WCF寄宿主机可以参考前两篇文章
WCF透明代理类,动态调用,支持async/await的更多相关文章
- WCF 透明代理
现在我们通过类似的原理创建一个用于模拟WCF服务端和客户端工作原理的模拟程序.[源代码从这里下载] 目录 一.基本的组件和执行流程 二.创建自定义HttpHandler实现对服务调用请求的处理 三.定 ...
- 终于解决:升级至.NET 4.6.1后VS2015生成WCF客户端代理类的问题
在Visual Studio 2015中将一个包含WCF引用的项目的targetFramework从4.5改为4.6.1的时候,VS2015会重新生成WCF客户端代理类.如果WCF引用配置中选中了&q ...
- Node 7.6默认支持Async/Await
Node.js 7.6正式默认支持async/await功能,并能够使低内存设备获得更出色的性能. Node 7.6对async/await的支持来自于将V8(Chromium JavaScript引 ...
- WCF服务代理类-学习
类:ServiceDescriptionImporter Class 公开一种为 XML Web services 生成客户端代理类的方法. 地址:https://docs.microsoft.com ...
- 为什么 array.foreach 不支持 async/await
一.背景 react 项目中,渲染组件时,显示的数据一直有问题,本来以为是 react 组件的问题,后来才发现罪魁祸首在 fetch 数据的过程,因为我用了 async/await ,而却搭配了 fo ...
- 动态得到WCF的代理类并生成代码
Uri uri = new Uri("http://localhost:6580/Service1.svc?wsdl"); MetadataExchange ...
- C# 通过反射类动态调用DLL方法
网上看了很多关于反射的思路和方法,发现这个还算不错 //使用反射方: using System; using System.Collections.Generic; using System.Linq ...
- 关于IIS寄宿WCF服务,客户端不能生成代理类
我在使用VS2010写好WCF的Web服务后,部署在IIS7.0上,可以在IE9上进行访问,并且能显示XML数据,如下图 然后我在项目的客户端进行服务的添加引用,如下图 VS2010自动生成代理类,但 ...
- 创建一个简单的WCF程序2——手动开启/关闭WCF服务与动态调用WCF地址
一.创建WCF服务器 1.创建WCF服务器的窗体应用程序 打开VS2010,选择文件→新建→项目菜单项,在打开的新建项目对话框中,依次选择Visual C#→Windows→Windows窗体应用程序 ...
随机推荐
- Android Studio模拟器磁盘空间不足(Not enough disk space to run AVD)
在Android Studio中运行模拟器时,提示Error: Not enough disk space to run AVD '....'. Exiting.是说安装模拟的磁盘空间不足,导致无法运 ...
- BM递推
从别的大佬处看到的模板 #include<bits/stdc++.h> #define fi first #define se second #define INF 0x3f3f3f3f ...
- MYSQL分组合并函数
MySQL中group_concat函数完整的语法如下:group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符' ...
- Quartz使用
背景 很多时候,项目需要在不同时刻,执行一个或很多个不同的作业. Windows执行计划这时并不能很好的满足需求了,迫切需要一个更为强大,方便管理,集群部署的作业调度框架. 介绍 Quartz一个开源 ...
- Django REST framework的分页
DRF分页组件 为什么要使用分页 我们数据表中可能会有成千上万条数据,当我们访问某张表的所有数据时,我们不太可能需要一次把所有的数据都展示出来,因为数据量很大,对服务端的内存压力比较大还有就是网络传输 ...
- python argparse(参数解析)模块学习(一)
class ArgumentParser(_AttributeHolder, _ActionsContainer): """Object for parsing comm ...
- 数组中的逆序对(python)
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- MongoDB入门(一)
文档 文档是MongoDB中的基本数据结构,型如:{"name":"Jack","lastname":"xi"} 键值对 ...
- 65. Valid Number 判断字符串是不是数字
[抄题]: Validate if a given string is numeric. Some examples:"0" => true" 0.1 " ...
- Admin注册和路由分发详解
Admin注册和路由分发详解 1.启动 #autodiscover_modules('admin', register_to=site) 2.注册 1.单例对象 admin.site = AdminS ...