二、绑定元素
每一个类型的绑定最重要的就是绑定元素了,每个绑定的功能特性都由绑定元素决定。BasicHttpBinding由用于编码的TextMessageEncodingBindingElement和用于httpp协议传输的HttpTransportBindingElement 构成。
NetTcpBinding由下列绑定元素组成,可以看出NetTcpBinding支持事务、二进制编码、信道安全、底层使用Tcp协议传输。
TransactionFlowBindingElement BinaryMessageEncodingBindingElement WindowsStreamSecurityBindingElement TcpTransportBindingElement
可以通绑定的CreateBindingElements方法获取当前绑定元素。
WSHttpBinding bind = new WSHttpBinding(); foreach (var ele in bind.CreateBindingElements()) { Console.WriteLine("{0}", ele.GetType().Name); }
整个绑定模型可以由下面这张图表示:
绑定元素能够创建信道管理器,再由信道管理器创建信道。信道管理器就是前面说到的信道监听器、信道工厂的简称,因为它们都继承自ChannelManagerBase。信道位于最底层,提供对消息的某种功能处理,对消息进行编码、传输是最基本的两种信道。
三、创建自定义信道
myChannelBase,继承信道基类ChannelBase,由一个InnerChannel表示下一个信道。所以方法都是简单输出当前类的名称,并调用下一个信道的方法来实现,本信道是打酱油的,只为看出后续绑定执行流程。
class myChannelBase:ChannelBase { public ChannelBase InnerChannel { get; private set; } public myChannelBase(ChannelManagerBase channelManager, ChannelBase InnerChannel) : base(channelManager) { this.InnerChannel = InnerChannel; } public override T GetProperty<T>() { print("GetProperty<T>"); return InnerChannel.GetProperty<T>(); } protected void print(string methodname) { Console.WriteLine("{0}:{1}", this.GetType().Name, methodname); } protected override void OnAbort() { print("OnAbort"); InnerChannel.Abort(); } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { print("OnBeginClose"); return InnerChannel.BeginClose(timeout, callback, state); } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { print("OnBeginOpen"); return InnerChannel.BeginOpen(timeout, callback, state); } protected override void OnClose(TimeSpan timeout) { print("OnClose"); InnerChannel.Close(timeout); } protected override void OnEndClose(IAsyncResult result) { print("OnEndClose"); InnerChannel.EndClose(result); } protected override void OnEndOpen(IAsyncResult result) { print("OnEndOpen"); InnerChannel.EndOpen(result); } protected override void OnOpen(TimeSpan timeout) { print("OnOpen"); InnerChannel.Open(timeout); } }
myRequestChannel:请求信道,继承myChannelBase,并实现IRequestChannel。构造函数传入信道管理器,以及下一个信道。后面由myChannelFactory创建。
class myRequestChannel:myChannelBase,IRequestChannel { public IRequestChannel InnerRequestChannel { get { return (IRequestChannel)base.InnerChannel; } } public myRequestChannel(ChannelManagerBase channelManager, IRequestChannel InnerRequestChannel) : base(channelManager, (ChannelBase)InnerRequestChannel) { base.print("myRequestChannel()"); } public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state) { base.print("BeginRequest(message,timeout,callback,state)"); return InnerRequestChannel.BeginRequest(message, timeout, callback, state); } public IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state) { base.print("BeginRequest(message,callback,state)"); return InnerRequestChannel.BeginRequest(message, callback, state); } public Message EndRequest(IAsyncResult result) { base.print("EndRequest(result)"); return InnerRequestChannel.EndRequest(result); } public EndpointAddress RemoteAddress { get { return InnerRequestChannel.RemoteAddress; } } public Message Request(Message message, TimeSpan timeout) { base.print("Request(message,timeout)"); return InnerRequestChannel.Request(message, timeout); } public Message Request(Message message) { base.print("Request(message)"); return InnerRequestChannel.Request(message); } public Uri Via { get { return InnerRequestChannel.Via; } } }
myReplyChannel:回复信到,继承myChannelBase,并实现IReplyChannel。构造函数传入信道管理器,以及下一个信道。后面由myChannelListener创建。
class myReplyChannel:myChannelBase,IReplyChannel { public IReplyChannel InnerRepleyChannel { get { return (IReplyChannel)base.InnerChannel; } } public myReplyChannel(ChannelManagerBase channelManager, IReplyChannel InnerRepleyChannel) : base(channelManager, (ChannelBase)InnerRepleyChannel) { base.print("myReplyChannel()"); } public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state) { base.print("BeginReceiveRequest(timeout, callback, state)"); return InnerRepleyChannel.BeginReceiveRequest(timeout, callback, state); } public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state) { base.print("BeginReceiveRequest(callback, state)"); return InnerRepleyChannel.BeginReceiveRequest(callback, state); } public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state) { base.print("BeginTryReceiveRequest(timeout,callback, state)"); return InnerRepleyChannel.BeginTryReceiveRequest(timeout,callback, state); } public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state) { base.print("BeginWaitForRequest(timeout,callback, state)"); return InnerRepleyChannel.BeginWaitForRequest(timeout, callback, state); } public RequestContext EndReceiveRequest(IAsyncResult result) { base.print("EndReceiveRequest(result)"); return InnerRepleyChannel.EndReceiveRequest(result); } public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context) { base.print("EndTryReceiveRequest(result,out context)"); return InnerRepleyChannel.EndTryReceiveRequest(result, out context); } public bool EndWaitForRequest(IAsyncResult result) { base.print("EndWaitForRequest(result)"); return InnerRepleyChannel.EndWaitForRequest(result); } public EndpointAddress LocalAddress { get { return InnerRepleyChannel.LocalAddress; } } public RequestContext ReceiveRequest(TimeSpan timeout) { base.print("ReceiveRequest(timeout)"); return InnerRepleyChannel.ReceiveRequest(timeout); } public RequestContext ReceiveRequest() { base.print("ReceiveRequest()"); return InnerRepleyChannel.ReceiveRequest(); } public bool TryReceiveRequest(TimeSpan timeout, out RequestContext context) { base.print("TryReceiveRequest(timeout,out context)"); return InnerRepleyChannel.TryReceiveRequest(timeout, out context); } public bool WaitForRequest(TimeSpan timeout) { base.print("WaitForRequest(timeout)"); return InnerRepleyChannel.WaitForRequest(timeout); } }
四、自定义信道监听器
myChannelListenerBase,自定义的信道监听器基类,最重要的作用就是在构造函数创建下一个信道监听器。
class myChannelListenerBase<TChannel> : ChannelListenerBase<TChannel> where TChannel : class,IChannel { public IChannelListener<TChannel> InnreListener { get; private set; } public myChannelListenerBase(BindingContext context) { InnreListener = context.BuildInnerChannelListener<TChannel>(); } protected void print(string methodname) { Console.WriteLine("{0}:{1}", this.GetType().Name, methodname); } protected override TChannel OnAcceptChannel(TimeSpan timeout) { print("OnAcceptChannel(timeout)"); return InnreListener.AcceptChannel(timeout); } protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state) { print("OnBeginAcceptChannel(timeout,callback,state)"); return InnreListener.BeginAcceptChannel(timeout, callback, state); } protected override TChannel OnEndAcceptChannel(IAsyncResult result) { print("OnEndAcceptChannel(result)"); return InnreListener.EndAcceptChannel(result); } protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state) { print("OnBeginWaitForChannel(timeout,callback,state)"); return InnreListener.BeginWaitForChannel(timeout, callback, state); } protected override bool OnEndWaitForChannel(IAsyncResult result) { print("OnEndWaitForChannel(result)"); return InnreListener.EndWaitForChannel(result); } protected override bool OnWaitForChannel(TimeSpan timeout) { print("OnWaitForChannel(timeout)"); return InnreListener.WaitForChannel(timeout); } public override Uri Uri { get { return InnreListener.Uri; } } protected override void OnAbort() { print("OnAbort()"); InnreListener.Abort(); } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { print("OnBeginClose(timeout,callback,state)"); return InnreListener.BeginClose(timeout, callback, state); } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { print("OnBeginOpen(timeout,callback,state)"); return InnreListener.BeginOpen(timeout, callback, state); } protected override void OnClose(TimeSpan timeout) { print("OnClose(timeout)"); InnreListener.Close(timeout); } protected override void OnEndClose(IAsyncResult result) { print("OnEndClose(result)"); InnreListener.EndClose(result); } protected override void OnEndOpen(IAsyncResult result) { print("OnEndOpen(result)"); InnreListener.EndOpen(result); } protected override void OnOpen(TimeSpan timeout) { print("OnOpen(timeout)"); InnreListener.Open(timeout); } }
myChannelListener,OnAcceptChannel方法中创建三中提到的myReplyChannel。
class myChannelListener<TChannel> : myChannelListenerBase<TChannel> where TChannel : class,IChannel { public myChannelListener(BindingContext context) : base(context) { } protected override TChannel OnAcceptChannel(TimeSpan timeout) { print("OnAcceptChannel(timeout)"); IReplyChannel replyCHannel = (IReplyChannel)InnreListener.AcceptChannel(timeout); return (new myReplyChannel(this, replyCHannel) as TChannel); } protected override TChannel OnEndAcceptChannel(IAsyncResult result) { print("OnEndAcceptChannel(result)"); IReplyChannel replychannel= InnreListener.EndAcceptChannel(result) as IReplyChannel; return new myReplyChannel(this, replychannel) as TChannel; } }
五、自定信道工厂
myChannelFactoryBase,继承自ChannelFactoryBase,工厂基类,主要作用是创建下一个信道工厂。
class myChannelFactoryBase<TChannel> : ChannelFactoryBase<TChannel> { public IChannelFactory<TChannel> InnerFactory { get; private set; } protected void print(string methodname) { Console.WriteLine("{0}:{1}", this.GetType().Name, methodname); } public myChannelFactoryBase(BindingContext context) { print("myChannelFactoryBase(context)"); InnerFactory= context.BuildInnerChannelFactory<TChannel>(); } protected override TChannel OnCreateChannel(EndpointAddress address, Uri via) { print("OnCreateChannel(address,via)"); return InnerFactory.CreateChannel(address,via); } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { print("OnBeginOpen(timeout,callback,state)"); return InnerFactory.BeginOpen(timeout, callback, state); } protected override void OnEndOpen(IAsyncResult result) { print("OnEndOpen(result)"); InnerFactory.EndOpen(result); } protected override void OnOpen(TimeSpan timeout) { print("OnOpen(timeout)"); InnerFactory.Open(timeout); } }
myChannelFactory,自定义信道工厂,创建三中提到的myRequestChannel。
class myChannelFactory<TChannel> : myChannelFactoryBase<TChannel> { public myChannelFactory(BindingContext context) : base(context) { print("myChannelFactory(xontext)"); } protected override TChannel OnCreateChannel(EndpointAddress address, Uri via) { print("OnCreateChannel(address,via)"); IRequestChannel requestchannel = (IRequestChannel)InnerFactory.CreateChannel(address, via); return (TChannel)(object)new myRequestChannel(this,requestchannel); } }
六、自定义绑定元素
myBindingElement继承BindingElement基类,通过BuildChannelFactory、BuildChannelListener方法创建myChannelFactory、BuildChannelListener
class myBindingElement:BindingElement { protected void print(string methodname) { Console.WriteLine("{0}:{1}", this.GetType().Name, methodname); } public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context) { print("BuildChannelFactory<TChannel>(BindingContext context)"); return new myChannelFactory<TChannel>(context); } public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context) { print("IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context) where TChannel : class, IChannel"); return new myChannelListener<TChannel>(context); } public override BindingElement Clone() { return new myBindingElement(); } public override T GetProperty<T>(BindingContext context) { return context.GetInnerProperty<T>(); } }
七、自定义绑定
经过前面一系列创建,接下来放大招了。myBinding,把自定义绑定元素放在绑定元素集合中的第一个位置。当服务端执行的时候,我们自定义的绑定元素啥都不干,直接调用下一个绑定元素的种种通信对象干活。
public class myBinding:Binding { private BindingElement[] binds = new BindingElement[] { new myBindingElement(), new TextMessageEncodingBindingElement(), new HttpTransportBindingElement() }; private HttpTransportBindingElement transportbind; public override BindingElementCollection CreateBindingElements() { transportbind = (HttpTransportBindingElement)binds[2]; return new BindingElementCollection(binds); } public override string Scheme { get { return transportbind.Scheme; } } }
八、服务端使用自定义自定义绑定
static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(mywcf.Calculator))) { host.AddServiceEndpoint(typeof(mywcf.ICalculator), new myBinding(), "http://localhost:4216"); host.Opened += delegate { Console.WriteLine("Service Start!"); }; host.Open(); Console.ReadLine(); } }
运行一下,控制台输出,可以看到运行步骤。先创建了信道监听器、Open、再创建自定义信道、接着Open、然后进入接受消息状态。这个和前一篇博文代码顺序一致。
九、客户端代码
static void Main(string[] args) { ChannelFactory<mywcf.ICalculator> factory = new ChannelFactory<mywcf.ICalculator>(new myBinding(), new EndpointAddress("http://localhost:4216")); mywcf.ICalculator client = factory.CreateChannel(); Console.WriteLine(client.Add(1, 2)); }
运行客户端输出,创建信道工厂、Open、创建请求信道、Open、Request发送请求。与前一章客户端代码运行顺序一致。