1,Dupex(双工) MEP(消息交换模式),服务端回调(Callback)客户端操作
2,客户端调用服务时,附加上一个回调对象(InstanceContext)。服务端处理服务请求时,通过该回调对象调用客户端操作。
3,WCF系统设计常用四层结构:Contracts(契约),Services(服务),Hosting(服务寄宿),Clients(客户端)
4,客户端调用服务,需要服务契约;服务端回调客户端操作,同样需要回调契约。回调契约通过ServiceContract(服务契约)特性的CallbackContract属性指定
5,回调契约本质也是服务契约,但在服务契约里已指明该回调契约的服务契约属性,所以回调契约不需要再标记ServiceContract属性
6,服务端在处理服务请求时,通过当前的OperationContext.Current.GetCallback<T>方法获取回调对象,T代表回调契约的类型
7,OperationContext代表服务操作执行上下文,通过静态属性Current获取当前OperationContent。我们可以在服务端或客户端设置一些上下文,比如为出栈消息添加Soap报头,从入栈消息取出报头等
8,为执行回调,客户端首先要实现回调契约:定义继承回调契约的类,实现回调契约接口方法
9,调用双工服务,先创建回调对象,并通过InstanceContext对回调对象包装,然后用DuplexChannelFactory<TChannel>方法创建服务通道。
10,用服务通道的CreateChannel方法生成服务代理对象,进而调用服务方法。
11,服务响应请求,回调回调对象的方法,在客户端执行回调方法。
契约定义:
using System.ServiceModel; namespace Contracts { [ServiceContract(CallbackContract = typeof(ICallback))] public interface ICalculator { [OperationContract(IsOneWay =true)] void Add(double x,double y); } public interface ICallback { [OperationContract(IsOneWay = true)] void DisplayResult(double x, double y, double result); } }
服务实现:
using Contracts; namespace Services { public class CalculatorService : ICalculator { public void Add(double x, double y) { double result = x + y; ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>(); callback.DisplayResult(x,y, result); } } }
服务寄宿:
using System; using System.ServiceModel; using Services; namespace Hosting { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(CalculatorService))) { host.Open(); Console.Read(); } } } }
寄宿配置:
<system.serviceModel> <services> <service name="Services.CalculatorService"> <endpoint address="net.tcp://127.0.0.1:9999/CalculatorService" binding="netTcpBinding" contract="Contracts.ICalculator"/> </service> </services> </system.serviceModel>
客户端调用及回调实现:
using Contracts; using System; using System.ServiceModel; namespace Clients { class Program { static void Main(string[] args) { InstanceContext instanceContext = new InstanceContext(new CalculatorCallback()); using (DuplexChannelFactory<ICalculator> ChannelFactory = new DuplexChannelFactory<ICalculator>(instanceContext, "CalculatorService")) { ICalculator prox = ChannelFactory.CreateChannel(); using (prox as IDisposable) { prox.Add(1, 2); Console.Read(); } } } } class CalculatorCallback : ICallback { public void DisplayResult(double x, double y, double result) { Console.WriteLine($"{x} + {y} = {result}"); } } }
客户端配置:
<system.serviceModel> <client> <endpoint name ="CalculatorService" address="net.tcp://127.0.0.1:9999/CalculatorService" binding="netTcpBinding" contract="Contracts.ICalculator"/> </client> </system.serviceModel>
WCF Tcp双工通信 Get !