在WCF绑定体系中,绑定创建绑定元素,绑定元素创建绑定监听器/绑定工厂,绑定监听器/绑定工厂创建信道。
WCF中绑定是有多个信道相连组成的信道栈,在这个信道栈中必须包含传输信道和编码信道,而且传输信道必须在栈底,在信道栈里面可以添加自定义的信道或是一些协议信道(WS-*标准),在这些协议信道中可以一些消息的处理,比如事务的流转,保证消息的安全传输等。在WCF的信道栈中每一个信道都对信道有这单一的处理功能,多个信道组成的信道栈就可以处理多种功能的消息;
Binding
public abstract class Binding : IDefaultCommunicationTimeouts{ public virtual IChannelListenerBuildChannelListener (BindingParameterCollection parameters) where TChannel : class, IChannel; public abstract BindingElementCollection CreateBindingElements(); public virtual bool CanBuildChannelListener (BindingParameterCollection parameters) where TChannel : class, IChannel;}
在Binding 类中通过调用BuildChannelListener<TChannel>方法来创建信道监听器;CreateBindingElements()方法时创建绑定元素集合,因为绑定元素创建信道监听器,因此绑定集合也就构成了一个信道的列表;
在WCF的系统绑定中的支持TCP/IP的的NetTcpBinding,它内部实现CreateBindingElements方法:
public class NetTcpBinding : Binding{ private void Initialize() { this.transport = new TcpTransportBindingElement(); this.encoding = new BinaryMessageEncodingBindingElement(); this.context = GetDefaultTransactionFlowBindingElement(); this.session = new ReliableSessionBindingElement(); this.reliableSession = new OptionalReliableSession(this.session); }
private static TransactionFlowBindingElement GetDefaultTransactionFlowBindingElement()
{ return new TransactionFlowBindingElement(false); }public override BindingElementCollection CreateBindingElements() { this.CheckSettings(); BindingElementCollection elements = new BindingElementCollection(); elements.Add(this.context); if (this.reliableSession.Enabled) { elements.Add(this.session); } SecurityBindingElement item = this.CreateMessageSecurity(); if (item != null) { elements.Add(item); } elements.Add(this.encoding); BindingElement element2 = this.CreateTransportSecurity(); if (element2 != null) { elements.Add(element2); } this.transport.ExtendedProtectionPolicy = this.security.Transport.ExtendedProtectionPolicy; elements.Add(this.transport); return elements.Clone(); }}
在NetTcpBinding中的CreateBindingElements方法
1.创建绑定元素集合(BindingElementCollection)并在集合中添加对绑定的事务流支持的绑定元素(TransactionFlowBindingElement);
2.当前绑定启用可靠会话传输,则在绑定集合中添加支持可生成终结点间可靠会话所需的发送和接收通道的绑定元素(ReliableSessionBindingElement);
3.根据绑定的安全设置来生成支持通道 SOAP 消息安全的绑定元素(SecurityBindingElement)添加到绑定元素集合中;
4.在绑定元素集合中添加必需的消息编码绑定元素,由于Tcp采用二进制传输,因此创建支持而二进制编码的编码绑定元素(BinaryMessageEncodingBindingElement);
5.如果绑定的安全设置为使用安全传输(例如 HTTPS)提供安全性(SecurityMode.Transport/SecurityMode.TransportWithMessageCredential)或则创建保证传输保证和认证的绑定元素(WindowsStreamSecurityBindingElement,SslStreamSecurityBindingElement)
6.在绑定元素集合的最后添加支持传输的传输绑定元素(TcpTransportBindingElement),保证传输信道在栈底;
通过CreateBindingElements方法就为一个绑定创建了一个多个绑定元素集合,在创建信道监听器或是信道工厂时就是通过这个绑定元素集合进行创建;
public abstract class Binding : IDefaultCommunicationTimeouts{ public virtual IChannelListenerBuildChannelListener (Uri listenUriBaseAddress, string listenUriRelativeAddress, ListenUriMode listenUriMode, BindingParameterCollection parameters) where TChannel: class, IChannel { this.EnsureInvariants(); BindingContext context = new BindingContext(new CustomBinding(this), parameters, listenUriBaseAddress, listenUriRelativeAddress, listenUriMode); IChannelListener listener = context.BuildInnerChannelListener (); context.ValidateBindingElementsConsumed(); this.ValidateSecurityCapabilities(listener.GetProperty (), parameters); return listener; }}
在Binding 类中的BuildChannelListener方法中首先会调用EnsureInvariants方法,其实内部就是调用CreateBindingElements集合,然后创建绑定上下文(BindingContext)对象,通过绑定上下文的 BuildInnerChannelListener方法来创建信道监听器;
BindingContext
public class BindingContext{ private CustomBinding binding; private BindingParameterCollection bindingParameters; private Uri listenUriBaseAddress; private System.ServiceModel.Description.ListenUriMode listenUriMode; private BindingElementCollection remainingBindingElements; public IChannelListenerBuildInnerChannelListener () where TChannel: class, IChannel { return this.RemoveNextElement().BuildChannelListener (this); } private BindingElement RemoveNextElement() { BindingElement element = this.remainingBindingElements.Remove (); if (element == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(System.ServiceModel.SR.GetString("NoChannelBuilderAvailable", new object[] { this.binding.Name, this.binding.Namespace }))); } return element; }}
在绑定上文类中CustomBinding 表示创建绑定上下文的绑定对象,而BindingElementCollection表示绑定对象的绑定元素的上下文集合;
当调用BuildInnerChannelListener创建信道监听器时,首先取出BindingElementCollection元素中的一个绑定元素,并将该绑定元素从BindingElementCollection集合中移除,调用BindingElement的BuildChannelListener的方法来创建绑定监视器,而在BindingElement执行BuildChannelListener方法时又会调用绑定上下文的BuildInnerChannelListener方法,由于BindingElementCollection集合是动态变化的,因此每次都会取集合的第一元素来创建,并移除第一个绑定元素,当所有的绑定元素都调用完毕后,就创建了按照绑定元素集合顺序组成的信道栈;