自定义信道基类
WCF是一个极具扩展性的通信框架 无论在服务模型层还是信道层 都具有很多扩展点 而信道层的扩展点主要体现在实现自定义信道以增强信道栈处理信息的能力 比如我们可以扩展信道层 实现一个自定义的信道 该信道提供一些方法将信息压缩 使信息的传输更快速 下面创建一个自定义的信道基类 实现当信道的某些方法执行时打印出该信道类型的名字和它方法的名字 接着调用下一个信道的方法 要实现自定义信道基类 可以使自定义信道基类派生于ChannelBase 因为ChannelBase是所有信道的基类 它通过实现各种接口IChannel、ICommunicationObject、IDefaultCommunicationTimeouts和继承CommunicationObjec类进而拥有信道最基本的操作方法
1 using System.ServiceModel.Channels; 2 3 namespace Custom 4 { 5 public abstract class SimpleChannelBase : ChannelBase 6 { 7 protected void Print(string methodName) 8 { 9 Console.WriteLine("{0}.{1}", this.GetType().Name, methodName); 10 } 11 public ChannelBase InnerChannel { get; private set; } 12 public SimpleChannelBase(ChannelManagerBase channelManager, ChannelBase innerChannel) 13 : base(channelManager) 14 { 15 this.InnerChannel = innerChannel; 16 } 17 18 protected override void OnAbort() 19 { 20 this.Print("OnAbort()"); 21 this.InnerChannel.Abort(); 22 } 23 24 protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) 25 { 26 this.Print("OnBeginClose()"); 27 return this.InnerChannel.BeginClose(timeout, callback, state); 28 } 29 30 protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 31 { 32 this.Print("OnBeginOpen()"); 33 return this.InnerChannel.BeginOpen(timeout, callback, state); 34 } 35 36 protected override void OnClose(TimeSpan timeout) 37 { 38 this.Print("OnClose()"); 39 this.InnerChannel.Close(timeout); 40 } 41 42 protected override void OnEndClose(IAsyncResult result) 43 { 44 this.Print("OnEndClose()"); 45 this.InnerChannel.EndClose(result); 46 } 47 48 protected override void OnEndOpen(IAsyncResult result) 49 { 50 this.Print("OnEndOpen()"); 51 this.InnerChannel.EndOpen(result); 52 } 53 54 protected override void OnOpen(TimeSpan timeout) 55 { 56 this.Print("OnOpen()"); 57 this.InnerChannel.Open(timeout); 58 } 59 60 public override T GetProperty<T>() 61 { 62 return this.InnerChannel.GetProperty<T>(); 63 } 64 } 65 }
自定义请求-回复模式的请求信道
通过继承SimpleChannelBase创建自定义的、在客户端用于发送请求和接收服务端回复的请求信道SimpleRequestChannel 该类不但要继承SimpleChannelBase还需要实现IRequestChannel以模仿请求信道的功能
using System.ServiceModel.Channels; using System.ServiceModel; namespace Custom { public class SimpleRequestChannel : SimpleChannelBase, IRequestChannel { public IRequestChannel InnerRequestChannel { get { return (IRequestChannel)this.InnerChannel; } } public SimpleRequestChannel(ChannelManagerBase channelManager, IRequestChannel innerChannel) : base(channelManager, (ChannelBase)innerChannel) { this.Print("SimpleRequestChannel()"); } public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state) { this.Print("BeginRequest()"); return this.InnerRequestChannel.BeginRequest(message, timeout, callback, state); } public IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state) { this.Print("BeginRequest()"); return this.InnerRequestChannel.BeginRequest(message, callback, state); } public Message EndRequest(IAsyncResult result) { this.Print("EndRequest()"); return this.InnerRequestChannel.EndRequest(result); } public EndpointAddress RemoteAddress { get { return this.InnerRequestChannel.RemoteAddress; } } public Message Request(Message message, TimeSpan timeout) { this.Print("Request"); return this.InnerRequestChannel.Request(message, timeout); } public Message Request(Message message) { this.Print("Request"); return this.InnerRequestChannel.Request(message); } public Uri Via { get { return this.InnerRequestChannel.Via; } } } }
自定义请求-回复模式的回复信道
using System.ServiceModel.Channels; using System.ServiceModel; namespace Custom { public class SimpleReplyChannel : SimpleChannelBase, IReplyChannel { public IReplyChannel InnerReplyChannel { get { return (IReplyChannel)this.InnerChannel; } } public SimpleReplyChannel(ChannelManagerBase channelManager, IReplyChannel innerChannel) : base(channelManager, (ChannelBase)innerChannel) { this.Print("SimpleReplyChannel()"); } public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("BeginReceiveRequest()"); return this.InnerReplyChannel.BeginReceiveRequest(timeout, callback, state); } public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state) { this.Print("BeginReceiveRequest()"); return this.InnerReplyChannel.BeginReceiveRequest(callback, state); } public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("BeginTryReceiveRequest()"); return this.InnerReplyChannel.BeginTryReceiveRequest(timeout, callback, state); } public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("BeginWaitForRequest()"); return this.InnerReplyChannel.BeginWaitForRequest(timeout, callback, state); } public RequestContext EndReceiveRequest(IAsyncResult result) { this.Print("EndReceiveRequest()"); return this.InnerReplyChannel.EndReceiveRequest(result); } public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context) { this.Print("EndTryReceiveRequest()"); return this.InnerReplyChannel.EndTryReceiveRequest(result, out context); } public bool EndWaitForRequest(IAsyncResult result) { this.Print("EndWaitForRequest()"); return this.InnerReplyChannel.EndWaitForRequest(result); } public EndpointAddress LocalAddress { get{ return this.InnerReplyChannel.LocalAddress;} } public RequestContext ReceiveRequest(TimeSpan timeout) { this.Print("ReceiveRequest()"); return this.InnerReplyChannel.ReceiveRequest(timeout); } public RequestContext ReceiveRequest() { this.Print("ReceiveRequest()"); return this.InnerReplyChannel.ReceiveRequest(); } public bool TryReceiveRequest(TimeSpan timeout, out RequestContext context) { this.Print("TryReceiveRequest()"); return this.InnerReplyChannel.TryReceiveRequest(timeout, out context); } public bool WaitForRequest(TimeSpan timeout) { this.Print("WaitForRequest()"); return this.InnerReplyChannel.WaitForRequest(timeout); } } }
自定义双工会话信道
using System.ServiceModel.Channels; using System.ServiceModel; namespace Custom { public class SimpleDuplexSessionChannel : SimpleChannelBase, IDuplexSessionChannel { public IDuplexSessionChannel InnerDuplexSessionChannel { get { return (IDuplexSessionChannel)this.InnerChannel; } } public SimpleDuplexSessionChannel(ChannelManagerBase channelManager, IDuplexSessionChannel innerChannel) : base(channelManager, (ChannelBase)innerChannel) { this.Print("SimpleDuplexSessionChannel()"); } public IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("BeginReceive()"); return this.InnerDuplexSessionChannel.BeginReceive(timeout, callback, state); } public IAsyncResult BeginReceive(AsyncCallback callback, object state) { this.Print("BeginReceive()"); return this.InnerDuplexSessionChannel.BeginReceive(callback, state); } public IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("BeginTryReceive()"); return this.InnerDuplexSessionChannel.BeginTryReceive(timeout, callback, state); } public IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("BeginWaitForMessage()"); return this.InnerDuplexSessionChannel.BeginWaitForMessage(timeout, callback, state); } public Message EndReceive(IAsyncResult result) { this.Print("EndReceive()"); return this.InnerDuplexSessionChannel.EndReceive(result); } public bool EndTryReceive(IAsyncResult result, out Message message) { this.Print("EndTryReceive()"); return this.InnerDuplexSessionChannel.EndTryReceive(result, out message); } public bool EndWaitForMessage(IAsyncResult result) { this.Print("EndWaitForMessage()"); return this.InnerDuplexSessionChannel.EndWaitForMessage(result); } public EndpointAddress LocalAddress { get { return this.InnerDuplexSessionChannel.LocalAddress; } } public Message Receive(TimeSpan timeout) { this.Print("Receive()"); return this.InnerDuplexSessionChannel.Receive(timeout); } public Message Receive() { this.Print("Receive()"); return this.InnerDuplexSessionChannel.Receive(); } public bool TryReceive(TimeSpan timeout, out Message message) { this.Print("TryReceive()"); return this.InnerDuplexSessionChannel.TryReceive(timeout, out message); } public bool WaitForMessage(TimeSpan timeout) { this.Print("WaitForMessage()"); return this.InnerDuplexSessionChannel.WaitForMessage(timeout); } public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state) { this.Print("BeginSend()"); return this.InnerDuplexSessionChannel.BeginSend(message, timeout, callback, state); } public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state) { this.Print("BeginSend()"); return this.InnerDuplexSessionChannel.BeginSend(message, callback, state); } public void EndSend(IAsyncResult result) { this.Print("EndSend()"); this.InnerDuplexSessionChannel.EndSend(result); } public EndpointAddress RemoteAddress { get { return this.InnerDuplexSessionChannel.RemoteAddress; } } public void Send(Message message, TimeSpan timeout) { this.Print("Send()"); this.InnerDuplexSessionChannel.Send(message, timeout); } public void Send(Message message) { this.Print("Send()"); this.InnerDuplexSessionChannel.Send(message); } public Uri Via { get { return this.InnerDuplexSessionChannel.Via; } } public IDuplexSession Session { get { return this.InnerDuplexSessionChannel.Session; } } } }
自定义信道侦听器基类
我们要创建自定义的信道侦听器 则需要继承ChannelListenerBase<TChannel>抽象基类 因为该基类实现了IChannelListener<TChannel>接口 即所有关于侦听器的方法和属性的内部实现都ChannelListenerBase<TChannel>中完成了 我们要定义一个新版的侦听器基类 以便添加新的操作方法 则唯一途径就是派生于ChannelListenerBase<TChannel>类
using System.ServiceModel.Channels; namespace Custom { public abstract class SimpleChannelListenerBase<TChannel> : ChannelListenerBase<TChannel> where TChannel : class, IChannel { protected void Print(string methodName) { Console.WriteLine("{0}.{1}", this.GetType().Name, methodName); } public IChannelListener<TChannel> InnerChannelListener { get; private set; } public SimpleChannelListenerBase(BindingContext context) { this.InnerChannelListener = context.BuildInnerChannelListener<TChannel>(); } protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("OnBeginAcceptChannel()"); return this.InnerChannelListener.BeginAcceptChannel(timeout, callback, state); } protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("OnBeginWaitForChannel()"); return this.InnerChannelListener.BeginWaitForChannel(timeout, callback, state); } protected override bool OnEndWaitForChannel(IAsyncResult result) { this.Print("OnEndWaitForChannel()"); return this.InnerChannelListener.EndWaitForChannel(result); } protected override bool OnWaitForChannel(TimeSpan timeout) { this.Print("OnWaitForChannel()"); return this.InnerChannelListener.WaitForChannel(timeout); } public override Uri Uri { get{return this.InnerChannelListener.Uri;} } protected override void OnAbort() { this.Print("OnAbort()"); this.InnerChannelListener.Abort(); } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("OnBeginClose()"); return this.InnerChannelListener.BeginClose(timeout, callback, state); } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("OnBeginOpen()"); return this.InnerChannelListener.BeginOpen(timeout, callback, state); } protected override void OnClose(TimeSpan timeout) { this.Print("OnClose()"); this.InnerChannelListener.Close(timeout); } protected override void OnEndClose(IAsyncResult result) { this.Print("OnEndClose()"); this.InnerChannelListener.EndClose(result); } protected override void OnEndOpen(IAsyncResult result) { this.Print("OnEndOpen()"); this.InnerChannelListener.EndOpen(result); } protected override void OnOpen(TimeSpan timeout) { this.Print("OnOpen()"); this.InnerChannelListener.Open(timeout); } public override T GetProperty<T>() { return this.InnerChannelListener.GetProperty<T>(); } } }
自定义基于普通信道的信道侦听器
using System.ServiceModel.Channels; namespace Custom { public class SimpleDatagramChannelListener<TChannel> : SimpleChannelListenerBase<TChannel> where TChannel : class,IChannel { public SimpleDatagramChannelListener(BindingContext context) : base(context) { this.Print("SimpleDatagramChannelListener()"); } protected override TChannel OnAcceptChannel(TimeSpan timeout) { this.Print("OnAcceptChannel()"); IReplyChannel innerChannel = (IReplyChannel)this.InnerChannelListener.AcceptChannel(timeout); if (null != innerChannel) { return new SimpleReplyChannel(this, innerChannel) as TChannel; } return null; } protected override TChannel OnEndAcceptChannel(IAsyncResult result) { this.Print("OnEndAcceptChannel()"); IReplyChannel innerChannel = (IReplyChannel)this.InnerChannelListener.EndAcceptChannel(result); if (null != innerChannel) { return new SimpleReplyChannel(this, innerChannel) as TChannel; } return null; } } }
自定义基于会话信道的信道侦听器
using System.ServiceModel.Channels; namespace Custom { public class SimpleSessionChannelListener<TChannel> : SimpleChannelListenerBase<TChannel> where TChannel : class, IChannel { public SimpleSessionChannelListener(BindingContext context) : base(context) { this.Print("SimpleSessionChannelListener()"); } protected override TChannel OnAcceptChannel(TimeSpan timeout) { this.Print("OnAcceptChannel()"); IDuplexSessionChannel innerChannel = (IDuplexSessionChannel)this.InnerChannelListener.AcceptChannel(timeout); return new SimpleDuplexSessionChannel(this, innerChannel) as TChannel; } protected override TChannel OnEndAcceptChannel(IAsyncResult result) { this.Print("OnEndAcceptChannel()"); IDuplexSessionChannel innerChannel = (IDuplexSessionChannel)this.InnerChannelListener.EndAcceptChannel(result); if (null != innerChannel) { return new SimpleDuplexSessionChannel(this, innerChannel) as TChannel; } return default(TChannel); } } }
自定义信道工厂基类
using System.ServiceModel.Channels; using System.ServiceModel; namespace Custom { public abstract class SimpleChannelFactoryBase<TChannel> : ChannelFactoryBase<TChannel> { protected void Print(string methodName) { Console.WriteLine("{0}.{1}", this.GetType().Name, methodName); } public IChannelFactory<TChannel> InnerChannelFactory { get; private set; } public SimpleChannelFactoryBase(BindingContext context) { this.InnerChannelFactory = context.BuildInnerChannelFactory<TChannel>(); } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { this.Print("OnBeginOpen()"); return this.InnerChannelFactory.BeginOpen(timeout, callback, state); } protected override void OnEndOpen(IAsyncResult result) { this.Print("OnEndOpen()"); this.InnerChannelFactory.EndOpen(result); } protected override void OnOpen(TimeSpan timeout) { this.Print("OnOpen()"); this.InnerChannelFactory.Open(timeout); } public override T GetProperty<T>() { return this.InnerChannelFactory.GetProperty<T>(); } } }
自定义基于普通信道的信道工厂
using System.ServiceModel.Channels; using System.ServiceModel; namespace Custom { public class SimpleDatagramChannelFactory<TChannel> : SimpleChannelFactoryBase<TChannel> { public SimpleDatagramChannelFactory(BindingContext context) : base(context) { this.Print("SimpleDatagramChannelFactory()"); } protected override TChannel OnCreateChannel(EndpointAddress address, Uri via) { this.Print("OnCreateChannel()"); IRequestChannel innerChannel = (IRequestChannel)this.InnerChannelFactory.CreateChannel(address, via); if (null != innerChannel) { return (TChannel)(object)new SimpleRequestChannel(this, innerChannel); } else { return default(TChannel); } } } }
自定义基于会话信道的信道工厂
using System.ServiceModel.Channels; using System.ServiceModel; namespace Custom { public class SimpleSessionChannelFactory<TChannel> : SimpleChannelFactoryBase<TChannel> { public SimpleSessionChannelFactory(BindingContext context) : base(context) { this.Print("SimpleSessionChannelFactory()"); } protected override TChannel OnCreateChannel(EndpointAddress address, Uri via) { this.Print("OnCreateChannel()"); IDuplexSessionChannel innerChannel = (IDuplexSessionChannel)this.InnerChannelFactory.CreateChannel(address, via); if (null != innerChannel) { return (TChannel)(object)new SimpleDuplexSessionChannel(this, innerChannel); } return default(TChannel); } } }
自定义基于普通信道的绑定元素
using System.ServiceModel.Channels; namespace Custom { public class SimpleDatagramBindingElement:BindingElement { protected void Print(string methodName) { Console.WriteLine("{0}.{1}", this.GetType().Name, methodName); } public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context) { this.Print("BuildChannelListener<TChannel>()"); return new SimpleDatagramChannelListener<TChannel>(context); } public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context) { this.Print("BuildChannelFactory<TChannel>()"); return new SimpleDatagramChannelFactory<TChannel>(context); } public override BindingElement Clone() { return new SimpleDatagramBindingElement(); } public override T GetProperty<T>(BindingContext context) { return context.GetInnerProperty<T>(); } } }
自定义基于会话信道的绑定元素
using System.ServiceModel.Channels; namespace Custom { public class SimpleSessionBindingElement: BindingElement { protected void Print(string methodName) { Console.WriteLine("{0}.{1}", this.GetType().Name, methodName); } public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context) { this.Print("BuildChannelListener<TChannel>()"); return new SimpleSessionChannelListener<TChannel>(context); } public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context) { this.Print("BuildChannelFactory<TChannel>()"); return new SimpleSessionChannelFactory<TChannel>(context); } public override BindingElement Clone() { return new SimpleSessionBindingElement(); } public override T GetProperty<T>(BindingContext context) { return context.GetInnerProperty<T>(); } } }
自定义基于普通信道的绑定对象
在前面的示例中 我们创建了自定义的信道、信道侦听器和信道工厂、绑定元素 所有这些对象都必须通过一个具体的绑定对象才能将它们全部应用到WCF运行环境中
using System.ServiceModel.Channels; namespace Custom { public class SimpleDatagramBinding : Binding { protected void Print(string methodName) { Console.WriteLine("{0}.{1}", this.GetType().Name, methodName); } private TransportBindingElement transportBindingElement; private BindingElementCollection bindingElementCollection; public SimpleDatagramBinding() { BindingElement[] bindingElements = new BindingElement[] { new SimpleDatagramBindingElement(), new TextMessageEncodingBindingElement(), new HttpTransportBindingElement() }; bindingElementCollection = new BindingElementCollection(bindingElements); transportBindingElement = (TransportBindingElement)bindingElements[2]; } public override BindingElementCollection CreateBindingElements() { return bindingElementCollection; } public override string Scheme { get { return transportBindingElement.Scheme; } } } }
自定义基于会话信道的绑定对象
using System.ServiceModel.Channels; namespace Custom { public class SimpleSessionBinding : Binding { private TransportBindingElement transportBindingElement; private BindingElementCollection bindingElementCollection; public SimpleSessionBinding() { BindingElement[] bindingElements = new BindingElement[] { new SimpleSessionBindingElement(), new BinaryMessageEncodingBindingElement(), new TcpTransportBindingElement() }; bindingElementCollection = new BindingElementCollection(bindingElements); transportBindingElement = (TransportBindingElement)bindingElements[2]; } public override BindingElementCollection CreateBindingElements() { return bindingElementCollection; } public override string Scheme { get { return transportBindingElement.Scheme; } } } }
测试自定义绑定对象
我们使用这个自定义绑定对象来做测试 修改计算服务的例子 打开Service项目的CalculatorService文件 修改如下
1 using Service.Interface; 2 3 namespace Service 4 { 5 public class CalculatorService:ICalculator 6 { 13 public double Add(double x, double y) 14 { 15 var result = x + y; 16 Console.WriteLine("完成接收请求和回复…………"); 17 return result; 18 } 19 } 20 }
打开Hosting项目的入口文件 修改如下
1 using System.ServiceModel; 2 using Service.Interface; 3 using Service; 4 using Custom; 5 6 namespace Hosting 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 ServiceHost host = new ServiceHost(typeof(CalculatorService)); 13 host.AddServiceEndpoint(typeof(ICalculator), new SimpleDatagramBinding(), "http://127.0.0.1:7777/calculatorservice"); 14 host.Open(); 15 Console.WriteLine("服务已开启……"); 16 Console.Read(); 17 } 18 } 19 }
用管理员身份运行该程序 则会输出以下信息
SimpleDatagramBindingElement.BuildChannelListener<TChannel>()
SimpleDatagramChannelListener`1.SimpleDatagramChannelListener()
SimpleDatagramChannelListener`1.OnOpen()
服务已开启……
SimpleDatagramChannelListener`1.OnBeginAcceptChannel()
SimpleDatagramChannelListener`1.OnEndAcceptChannel()
SimpleReplyChannel.SimpleReplyChannel()
SimpleDatagramChannelListener`1.OnBeginAcceptChannel()
SimpleReplyChannel.OnOpen()
SimpleReplyChannel.BeginTryReceiveRequest()
绑定对象创建信道侦听器的流程
WsHttpBinding是一个内置的绑定对象 WsHttpBinding被实例化时 它会调用自身的BuildChannelListener<TChannel>()方法创建信道侦听器管道 因为它有
两个内置的绑定元素HttpTransportBindingElement(传输元素)和TextMessageEncodingBindingElement(编码元素)两个绑定元素会自动创建自身的
信道侦听器 前一个侦听器侦听到请求就会传输信息到客户端 后一个侦听器侦听到请求则会处理请求中的信息编码
接着我们来看上面的例子 通过实例化自定义的绑定元素后 程序如何执行的 首先new SimpleDatagramBinding()执行时 将创建自定义绑定对象 - 绑定对象自动调用自身的BuildChannelListener<TChannel>()方法创建信道侦听器管道 我们可以把这个管道理解为一个大的侦听器容器(信道栈) 它承载的是绑定对象中的每个绑定元素自动创建的对应的侦听器 多个侦听器存储在这个信道侦听器通道中 该通道被打开以便侦听请求的信息 请求信息一旦抵达 通道则将依次调用每个绑定元素对应的信道的方法
1 SimpleDatagramBindingElement.BuildChannelListener<TChannel>() //自定义绑定元素调用该方法创建了一个自定义的信道侦听器 2 SimpleDatagramChannelListener`1.SimpleDatagramChannelListener() //自定义的信道侦听器被实例化 3 SimpleDatagramChannelListener`1.OnOpen() //自定义的信道侦听器创建完成后自动打开以便侦听请求 4 服务已开启…… 5 SimpleDatagramChannelListener`1.OnBeginAcceptChannel() //信道侦听器在开始创建信道时将触发这个事件 6 SimpleDatagramChannelListener`1.OnEndAcceptChannel() //信道侦听器在创建完信道时将触发这个事件 7 SimpleReplyChannel.SimpleReplyChannel() //信道侦听器创建了一个回复信道 8 SimpleDatagramChannelListener`1.OnBeginAcceptChannel() //信道被创建 则该事件被触发 9 SimpleReplyChannel.OnOpen() //打开回复信道 以便回复信息 10 SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作
在我们自定义的绑定对象中 除了自定义的绑定元素 还有两个绑定元素被添加到绑定对象中 如下代码片段所示:
1 public SimpleDatagramBinding() 2 { 3 BindingElement[] bindingElements = new BindingElement[] 4 { 5 new SimpleDatagramBindingElement(), //自定义的绑定元素 6 new TextMessageEncodingBindingElement(), //编码绑定元素 7 new HttpTransportBindingElement() //传输绑定元素 8 }; 9 bindingElementCollection = new BindingElementCollection(bindingElements); 10 transportBindingElement = (TransportBindingElement)bindingElements[2]; 11 }
一个是用于传输的绑定元素HttpTransportBindingElemen和用于编码的绑定元素SimpleDatagramBindingElement 两个绑定元素也都会调用自身的BuildChannelListener<TChannel>()方法创建各自的信道侦听器(隐式的创建了信道侦听器同时传输绑定元素还隐式创建了传输信道 而编码绑定元素隐式创建了编码信道) 这些信道再加上上面的自定义绑定元素创建的信道侦听器 就组成了一个信道栈(即信道通道)
接着我们打开Client项目的入口文件 修改如下:
1 using System.ServiceModel; 2 using Service.Interface; 3 using Custom; 4 5 namespace Client 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 EndpointAddress pointAddress=new EndpointAddress("http://127.0.0.1:7777/calculatorservice"); 12 ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(new SimpleDatagramBinding(), pointAddress); 13 //第一个信道工厂创建的服务代理 14 ICalculator proxy = channelFactory.CreateChannel(); 15 //发送第一个请求 16 proxy.Add(1, 2); 17 Console.WriteLine("完成请求并接收到回复……"); 18 //发送第二个请求 19 proxy.Add(1, 2); 20 Console.WriteLine("完成请求并接收到回复……"); 21 (proxy as ICommunicationObject).Close(); 22 23 //第二个信道工厂创建的服务代理 24 proxy = channelFactory.CreateChannel(); 25 //发送第一个请求 26 proxy.Add(1, 2); 27 Console.WriteLine("完成请求并接收到回复……"); 28 //发送第二个请求 29 proxy.Add(1, 2); 30 Console.WriteLine("完成请求并接收到回复……"); 31 (proxy as ICommunicationObject).Close(); 32 } 33 } 34 }
保持Hosting的运行 在运行Client 输出如下
new SimpleDatagramBinding()被实例化 - 它调用自身的BuildChannelFactory<TChannel>()方法创建信道工厂管道 因为它有两个内置的绑定元素TextMessageEncodingBindingElement(编码元素)和HttpTransportBindingElement(传输元素)两个绑定元素会自动创建自身的信道工厂 前一个信道工厂通过编码信道将信息编码接着使用后一个信道工厂通过传输信道发送信息请求到服务端
1 SimpleDatagramBindingElement.BuildChannelFactory<TChannel>() //自定义的绑定元素调用该方法创建了一个信道工厂 2 SimpleDatagramChannelFactory`1.SimpleDatagramChannelFactory() //自定义的信道工厂被初始化 3 SimpleDatagramChannelFactory`1.OnOpen() //自定义的信道工厂在开启时将触发这个事件 4 SimpleDatagramChannelFactory`1.OnCreateChannel() //自定义的信道工厂在开始创建请求信道时将触发这个事件 5 SimpleRequestChannel.SimpleRequestChannel() //自定义的信道工厂创建了一个自定义的请求信道 6 SimpleRequestChannel.OnOpen() //自定义的请求信道自动开启 7 SimpleRequestChannel.Request //自定义的请求信道发送发送第一个请求并接收服务端的回复信息 8 完成请求并接收到回复…… 9 SimpleRequestChannel.Request //自定义的请求信道发送发送第二个请求并接收服务端的回复信息 10 完成请求并接收到回复…… 11 SimpleRequestChannel.OnClose() //第一个服务代理被关闭 此时信道工厂管道并没关闭 它所有的信道还存在 请参看代码 关闭的是代理对象 12 SimpleDatagramChannelFactory`1.OnCreateChannel() //自定义的信道工厂在开始创建请求信道时将触发这个事件 13 SimpleRequestChannel.SimpleRequestChannel() //重复以上步骤 14 SimpleRequestChannel.OnOpen() //重复以上步骤 15 SimpleRequestChannel.Request //重复以上步骤 16 完成请求并接收到回复…… 17 SimpleRequestChannel.Request 18 完成请求并接收到回复…… 19 SimpleRequestChannel.OnClose() //重复以上步骤
而此时在服务端因为侦听到了请求 所以会如下输出信息
1 SimpleDatagramBindingElement.BuildChannelListener<TChannel>() //自定义绑定元素调用该方法创建了一个自定义的信道侦听器 2 SimpleDatagramChannelListener`1.SimpleDatagramChannelListener() //自定义的信道侦听器被实例化 3 SimpleDatagramChannelListener`1.OnOpen() //自定义的信道侦听器创建完成后自动打开以便侦听请求 4 服务已开启…… 5 SimpleDatagramChannelListener`1.OnBeginAcceptChannel() SimpleDatagramChannelListener`1.OnEndAcceptChannel() 6 SimpleReplyChannel.SimpleReplyChannel() //信道侦听器创建了一个回复信道 7 SimpleDatagramChannelListener`1.OnBeginAcceptChannel() 8 SimpleReplyChannel.OnOpen() //打开回复信道 以便回复信息 9 SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作 10 SimpleReplyChannel.EndTryReceiveRequest() //完成一个用于接收请求的异步操作 11 SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作 此时第一个请求抵达 12 完成接收请求和回复…… 13 SimpleReplyChannel.EndTryReceiveRequest() //完成一个用于接收请求的异步操作 14 SimpleReplyChannel.BeginTryReceiveRequest() //开始一个用于接收请求的异步操作 此时第二个请求抵达 15 完成接收请求和回复…… 16 SimpleReplyChannel.EndTryReceiveRequest() //重复 17 SimpleReplyChannel.BeginTryReceiveRequest() //重复 18 完成接收请求和回复…… 19 SimpleReplyChannel.EndTryReceiveRequest() //重复 20 SimpleReplyChannel.BeginTryReceiveRequest() //重复 21 完成接收请求和回复……