WCF后续之旅(2): 如何对Channel Layer进行扩展——创建自定义Channel
在html" target=_blank>上一篇文章中,我们通过一个直接借助BasicHttpBinding对象实现Client和Server端进行通信的例子,对WCF channel layer进行了一个大致上的介绍。由此引出了一些列通信相关的概念和对象,比如Channel,Output channel, Input channel,Request channel, Reply Channel,Duplex channel, Channel Shape,Channel manager,Channel factory, Channel listener, Binding element 等。通过这些元素,我们很容易地实现对WCF channel layer进行扩展。
对channel layer进行扩展一般适用于当你的需求通过现有的Binding,或者channel不能实现,而需要自定义一些channel来实现你所需的功能。不如现在的WCF系统定义的Channel中没有实现对Message body的压缩功能。你可以就需要将此功能定义到一个custom channel中,然后将其注入到channel stack中。一般来说,仅仅创建custom channel是不够的,因为在runtime, channel是通过Channel manager进行创建的,所以你需要创建对应的Channel factory(如何对发送方进行扩展)或者Channel listener(如果对接受方进行扩展)。而Channel factory和channel listener最终又是通过Binding element进行创建的,所以你还需要创建相应的Binding element。(Binding element=〉Channel factory&Channel listener=>Channel)
在本章节中,我们将继续讨论WCF channel layer。我们将通过如何创建和应用custom channel来介绍channel layer一些知识。
一、ICommunicationObject 和 CommunicationObject
我们
知道WCF channel layer的绝大部分对象,比如Channel,Channel factory,Channel listener,从功能上讲都是用于通信(Communication)的对象,对传统的communication object,比如socket,他们往往都具有通过状态和状态转化规则(状态机:State machine)。这些状态包括Creating、Created、Opening、Opened、Closing、Closed等等。为了统一管理这些状态和状态之间的转化,WCF定义个一个特殊的Inte易做图ce:ICommunicationObject
1: public inte易做图ce ICommunicationObject
2: {
3: // Events
4: event EventHandler Closed;
5: event EventHandler Closing;
6: event EventHandler Faulted;
7: event EventHandler Opened;
8: event EventHandler Opening;
9:
10: // Methods
11: void Abort();
12: IAsyncResult BeginClose(AsyncCallback callback, object state);
13: IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state);
14: IAsyncResult BeginOpen(AsyncCallback callback, object state);
15: IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state);
16: void Close();
17: void Close(TimeSpan timeout);
18: void EndClose(IAsyncResult result);
19: void EndOpen(IAsyncResult result);
20: void Open();
21: void Open(TimeSpan timeout);
22:
23: // Properties
24: CommunicationState State { get; }
25: }ICommunicationObject定义了3种成员:
属性:State, 得到当前的状态,返回值是一个CommunicationState 枚举。
方法:同步、异步Open和Close方法。
事件:通过注册这些状态相关的Event,当时对象转化到对应的状态时执行相应操作。
WCF定义了一个abstract class: CommunicationObject直接实现了该Inte易做图ce。CommunicationObject的实现统一的State machine。WCF channel layer的很多的class都直接或者间接的继承了这个class。你也可以让你的class继承该class。当你让你自己的class继承CommunicationObject的时候,在override 掉base相应的method的时候,强烈建议你先调用base对应的方法,CommunicationObject会帮你进行相应的State转换和触发相应的事件。二、Channel 和Channel Shape
在上一篇文章中,我们讨论过了。在不同的消息交换模式(MEP)中,发送方和接受方的Channel扮演的角色是不相同的。我们并把这种不同MEP中消息交互双方Channel的结构差异表述为Channel shape。我们有四种不同的Channel shape:Datagram、Request/reply、Duplex和P2P。不同Channel shape中Channel的结构性差性通过实现不同的Channel inte易做图ce来体现。对于Datagram channel shape,采用了One-way的MEP。发送方的channel 必须实现IOutputChannel inte易做图ce。该Inte易做图ce的方法成员主要集中在用于发送message的Send方法(同步/异步):
1: public inte易做图ce IOutputChannel : IChannel, ICommunicationObject
2: {
3: // Methods
4: IAsyncResult BeginSend(Message message, AsyncCallback callback, object state);
5: IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state);
6: void EndSend(IAsyncResult result);
7: void Send(Message message);
8: void Send(Message message, TimeSpan timeout);
9:
10: // Properties
11: EndpointAddress RemoteAddress { get; }
12: Uri Via { get; }
13: }与之相应是IInputChannel inteface,该Inte易做图ce用于Datagram channel shape中接收方的channel定义。其主要方法成员主要集中在用于接收Message的Receive方法(同步/异步):
1: public inte易做图ce IInputChannel : IChannel, ICommunicationObject
2: {
3: // Methods
4: IAsyncResult BeginReceive(AsyncCallback callback, object state);
5: IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state);
6: IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state);
7: IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state);
8: Message EndReceive(IAsyncResult result);
9: bool EndTryReceive(IAsyncResult result, out Message message);
10: bool EndWaitForMessage(IAsyncResult result);
11: Message Receive();
12: Message Receive(TimeSpan timeout);
13: bool TryReceive(TimeSpan timeout, out Message message);
14: bool WaitForMessage(TimeSpan timeout);
15:
16: // Properties
17: EndpointAddress LocalAddress { get; }
18: }注:无论对于同步或者异步方法,一般由两个重载,一个接收一个TimeSpan 作为参数,表是Send或者Receive允许的时间范围。而另一个没有该参数的方式,并不是建议你使用一个无限的TimeSpan,而是使用一个
补充:综合编程 , 其他综合 ,