閱讀746 返回首頁    go 技術社區[雲棲]


WCF後續之旅(2): 如何對Channel Layer進行擴展——創建自定義Channel

中,我們通過一個直接借助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

一、ICommunicationObject 和 CommunicationObject

我們知道WCF channel layer的絕大部分對象,比如Channel,Channel factory,Channel listener,從功能上講都是用於通信(Communication)的對象,對傳統的communication object,比如socket,他們往往都具有通過狀態和狀態轉化規則(狀態機:State machine)。這些狀態包括等等。為了統一管理這些狀態和狀態之間的轉化,WCF定義個一個特殊的Interface:

   1: public interface 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: } 

  • 屬性:State, 得到當前的狀態,返回值是一個CommunicationState  枚舉。
  • 方法:同步、異步Open和Close方法。
  • 事件:通過注冊這些狀態相關的Event,當時對象轉化到對應的狀態時執行相應操作。

WCF定義了一個abstract class: 直接實現了該Interface。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:Datagram、Request/reply、DuplexP2P。不同Channel shape中Channel的結構性差性通過實現不同的Channel interface來體現。

對於 channel shape,采用了One-way的MEP。發送方的channel 必須實現IOutputChannel interface。該Interface的方法成員主要集中在用於發送message的方法(同步/異步):

   1: public interface 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,該Interface用於Datagram channel shape中接收方的channel定義。其主要方法成員主要集中在用於接收Message的Receive方法(同步/異步):

   1: public interface 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: }

注:無論對於同步或者異步方法,一般由兩個重載,一個接收一個 作為參數,表是Send或者Receive允許的時間範圍。而另一個沒有該參數的方式,並不是建議你使用一個無限的TimeSpan,而是使用一個可配置的默認時間段(實際上是對象對應的屬性)

不同於Datagram channel shape, channel shape下交互雙方的Channel具有不同的行為。發送方的Channel實現。該interface的方麵成員主要集中在一些用於向接收方進行請求的方法(同步/異步):

   1: public interface IRequestChannel : IChannel, ICommunicationObject
   2: {
   3:     // Methods
   4:     IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state);
   5:     IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state);
   6:     Message EndRequest(IAsyncResult result);
   7:     Message Request(Message message);
   8:     Message Request(Message message, TimeSpan timeout); 
   9:  
  10:     // Properties
  11:     EndpointAddress RemoteAddress { get; }
  12:     Uri Via { get; }
  13: } 

同理,對於接收方的IReplyChannel則主要定義了一些用於的方法:

   1: public interface IReplyChannel : IChannel, ICommunicationObject
   2: {
   3:     // Methods
   4:     IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state);
   5:     IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state);
   6:     IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state);
   7:     IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state);
   8:     RequestContext EndReceiveRequest(IAsyncResult result);
   9:     bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context);
  10:     bool EndWaitForRequest(IAsyncResult result);
  11:     RequestContext ReceiveRequest();
  12:     RequestContext ReceiveRequest(TimeSpan timeout);
  13:     bool TryReceiveRequest(TimeSpan timeout, out RequestContext context);
  14:     bool WaitForRequest(TimeSpan timeout); 
  15:  
  16:     // Properties
  17:     EndpointAddress LocalAddress { get; }
  18: }
而對與Duplex和P2P,消息交互雙方使用相同的Channel:。本質上講,。這一點從IDuplexChannel的定義上就可以看出來:
   1: public interface IDuplexChannel : IInputChannel, IOutputChannel, IChannel, ICommunicationObject
   2: {
   3: } 

三、創建Custom Channel

為了讓大家對WCF channel layer有一個深刻的認識,以及掌握如何有效地對其進行擴展。我在整篇文章中穿插介紹一個具體的Sample:。

這個Sample將基於我們最為常用的 channel shape。所以我們需要創建兩個Channel,一個是用於發送方的實現了的Channel,而另一個則是實現了的用於接收方的Channel。

為了簡單起見,在我定義的channel的每個方法僅僅打印出相應的方法名稱而已(這樣做不但簡單,還有的一個好處,那就是當我最後將其應用到具體的Messaging場景中,可以)。

   1: namespace Artech.ChannleStackExplore.Channels
   2: {
   3:     public class MyRequestChannel :ChannelBase, IRequestChannel
   4:     {
   5:         private IRequestChannel InnerChannel
   6:         {get;set;} 
   7:  
   8:         public MyRequestChannel(ChannelManagerBase channleManager, IRequestChannel innerChannel)
   9:             : base(channleManager)
  10:         {
  11:             this.InnerChannel = innerChannel;
  12:         } 
  13:  
  14:         #region ChannelBase Members
  15:         protected override void OnAbort()
  16:         {
  17:             Console.WriteLine("MyRequestChannel.OnAbort()");
  18:             this.InnerChannel.Abort();
  19:         } 
  20:  
  21:         protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
  22:         {
  23:             Console.WriteLine("MyRequestChannel.OnBeginClose()");
  24:             return this.InnerChannel.BeginClose(timeout, callback, state);
  25:         } 
  26:  
  27:         protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  28:         {
  29:             Console.WriteLine("MyRequestChannel.OnBeginOpen()");
  30:             return this.InnerChannel.BeginOpen(timeout, callback, state);
  31:         } 
  32:  
  33:         protected override void OnClose(TimeSpan timeout)
  34:         {
  35:             Console.WriteLine("MyRequestChannel.OnClose()");
  36:             this.Close(timeout);
  37:         } 
  38:  
  39:         protected override void OnEndClose(IAsyncResult result)
  40:         {
  41:             Console.WriteLine("MyRequestChannel.OnEndClose()");
  42:             this.InnerChannel.EndClose(result);
  43:         } 
  44:  
  45:         protected override void OnEndOpen(IAsyncResult result)
  46:         {
  47:             Console.WriteLine("MyRequestChannel.OnEndOpen()");
  48:             this.InnerChannel.EndOpen(result);
  49:         } 
  50:  
  51:         protected override void OnOpen(TimeSpan timeout)
  52:         {
  53:             Console.WriteLine("MyRequestChannel.OnOpen()");
  54:             this.InnerChannel.Open(timeout);
  55:         }
  56:         #endregion 
  57:  
  58:         #region IRequestChannel Members 
  59:  
  60:         public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state)
  61:         {
  62:             Console.WriteLine("MyRequestChannel.BeginRequest()");
  63:             return this.BeginRequest(message, timeout, callback, state);
  64:         } 
  65:  
  66:         public IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state)
  67:         {
  68:             Console.WriteLine("MyRequestChannel.BeginRequest()");
  69:             return this.InnerChannel.BeginRequest(message, callback, state);
  70:         } 
  71:  
  72:         public Message EndRequest(IAsyncResult result)
  73:         {
  74:             Console.WriteLine("MyRequestChannel.EndRequest()");
  75:             return this.InnerChannel.EndRequest(result);
  76:         } 
  77:  
  78:         public EndpointAddress RemoteAddress
  79:         {
  80:             get 
  81:             {
  82:                 Console.WriteLine("MyRequestChannel.RemoteAddress");
  83:                 return this.InnerChannel.RemoteAddress;
  84:             } 
  85:  
  86:         } 
  87:  
  88:         public Message Request(Message message, TimeSpan timeout)
  89:         {
  90:             Console.WriteLine("MyRequestChannel.Request()");
  91:             return this.InnerChannel.Request(message, timeout);
  92:         } 
  93:  
  94:         public Message Request(Message message)
  95:         {
  96:             Console.WriteLine("MyRequestChannel.Request()");
  97:             return this.InnerChannel.Request(message);
  98:         } 
  99:  
 100:         public Uri Via
 101:         {
 102:             get 
 103:             { 
 104:                 Console.WriteLine("MyRequestChannel.Via)");
 105:                 return this.InnerChannel.Via;
 106:             } 
 107:  
 108:         } 
 109:  
 110:         #endregion
 111:     }
 112: } 

這裏唯一需要注意的一點是:在實際的運行環境中,我們的channel僅僅了位於Channel stack的某個環節。該channel和其他的一些channel組成一個管道,這個管道裏流淌是。所以當一個Channel執行了它相應的操作的時候,需要將message傳到下一個channel作進一步處理。所有我們的Channel需要下一個Channel的應用,這個Channel就是我們的字段,該成員在構造函數中指定。 

   1: private IRequestChannel InnerChannel
   2: {get;set;} 
   3:  
   4: public MyRequestChannel(ChannelManagerBase channleManager, IRequestChannel innerChannel)
   5:             : base(channleManager)
   6: {
   7:     this.InnerChannel = innerChannel;
   8: } 

   1: namespace Artech.ChannleStackExplore.Channels
   2: {
   3:     public class MyReplyChannel: ChannelBase, IReplyChannel
   4:     {
   5:         private IReplyChannel InnerChannel
   6:         { get; set; } 
   7:  
   8:         public MyReplyChannel(ChannelManagerBase channelManager, IReplyChannel innerChannel):base(channelManager)
   9:         {
  10:             this.InnerChannel = innerChannel;
  11:         } 
  12:  
  13:         ChannelBase Members 
  14:  
  15:         IReplyChannel Members
  16:     }
  17: }

4. 創建Custom Channel Factory & Channel Listener

通過上一篇文章的介紹,我們知道Channel是通過Channel Manager來創建並管理的,在發送方的Channel Manager被稱為。對於Channel factory,除了定義了兩個Interface之外(IChannelFactoryIChannelFactory<TChannel>

   1: public interface IChannelFactory : ICommunicationObject
   2: {
   3:       // Methods
   4:       T GetProperty<T>() where T : class;
   5: } 
   6:  
   7: public interface IChannelFactory<TChannel> : IChannelFactory, ICommunicationObject
   8: {
   9:     // Methods
  10:     TChannel CreateChannel(EndpointAddress to);
  11:     TChannel CreateChannel(EndpointAddress to, Uri via);
  12: } 

限於篇幅,在這裏就不多作介紹了)。

   1: namespace Artech.ChannleStackExplore.Channels
   2: {
   3:     public class MyChannelFactory<TChannel> : ChannelFactoryBase<TChannel>
   4:     {
   5:         private IChannelFactory<TChannel> InnerChannelFactory
   6:         { get; set; } 
   7:  
   8:         public MyChannelFactory(BindingContext context)
   9:         {
  10:             this.InnerChannelFactory = context.BuildInnerChannelFactory<TChannel>();
  11:         } 
  12:  
  13:         protected override TChannel OnCreateChannel(EndpointAddress address, Uri via)
  14:         {
  15:             Console.WriteLine("MyChannelFactory<TChannel>.OnClose()");
  16:             TChannel innerChannel = this.InnerChannelFactory.CreateChannel(address, via);
  17:             return (TChannel)(object)(new MyRequestChannel(this, innerChannel as IRequestChannel));
  18:         } 
  19:  
  20:         protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  21:         {
  22:             Console.WriteLine("MyChannelFactory<TChannel>.OnBeginOpen()");
  23:             return this.InnerChannelFactory.BeginOpen(timeout, callback, state);
  24:         } 
  25:  
  26:         protected override void OnEndOpen(IAsyncResult result)
  27:         {
  28:             Console.WriteLine("MyChannelFactory<TChannel>.OnEndOpen()");
  29:             this.InnerChannelFactory.EndOpen(result);
  30:         } 
  31:  
  32:         protected override void OnOpen(TimeSpan timeout)
  33:         {
  34:             Console.WriteLine("MyChannelFactory<TChannel>.OnOpen()");
  35:             this.InnerChannelFactory.Open();
  36:         }
  37:     }
  38: } 

我們說過,和Channel stack一樣,Channel factory仍然是一個stack,原因很簡單,一個個的Channel需要相應的channel factory來創建。同Channel一樣,。不過不通於Channel的是,下一個Channel factory不時在構造函數直接指定的,而是通過構造函數中BindingContext 對象的創建。

   1: private IChannelFactory<TChannel> InnerChannelFactory
   2: { get; set; } 
   3:  
   4: public MyChannelFactory(BindingContext context)
   5: {
   6:       this.InnerChannelFactory = context.BuildInnerChannelFactory<TChannel>();
   7: } 

注:BindingContext 的兩個最重要的方法就是BuildInnerChannelFactory和

   1: namespace Artech.ChannleStackExplore.Channels
   2: {
   3:     public class MyChannelListener<TChannel> : ChannelListenerBase<TChannel> where TChannel : class, IChannel
   4:     {
   5:         private IChannelListener<TChannel> InnerChannelListener
   6:         { get; set; } 
   7:  
   8:         public MyChannelListener(BindingContext context)
   9:         {
  10:             this.InnerChannelListener = context.BuildInnerChannelListener<TChannel>();
  11:         } 
  12:  
  13:         protected override TChannel OnAcceptChannel(TimeSpan timeout)
  14:         {
  15:             Console.WriteLine("MyChannelListener<TChannel>.OnAcceptChannel()");
  16:             TChannel innerChannel = this.InnerChannelListener.AcceptChannel(timeout);
  17:             return new MyReplyChannel(this, innerChannel as IReplyChannel) as TChannel;
  18:         } 
  19:  
  20:         protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state)
  21:         {
  22:             Console.WriteLine("MyChannelListener<TChannel>.OnBeginAcceptChannel()");
  23:            return this.InnerChannelListener.BeginAcceptChannel(timeout, callback, state);
  24:         } 
  25:  
  26:         protected override TChannel OnEndAcceptChannel(IAsyncResult result)
  27:         {
  28:             Console.WriteLine("MyChannelListener<TChannel>.OnEndAcceptChannel()");
  29:             TChannel innerChannel = this.InnerChannelListener.EndAcceptChannel(result);
  30:             return new MyReplyChannel(this, innerChannel as IReplyChannel) as TChannel;
  31:         } 
  32:  
  33:         protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state)
  34:         {
  35:             Console.WriteLine("MyChannelListener<TChannel>.OnBeginWaitForChannel()");
  36:             return this.InnerChannelListener.BeginWaitForChannel(timeout, callback, state);
  37:         } 
  38:  
  39:         protected override bool OnEndWaitForChannel(IAsyncResult result)
  40:         {
  41:             Console.WriteLine("MyChannelListener<TChannel>.OnEndWaitForChannel()");
  42:             return this.InnerChannelListener.EndWaitForChannel(result);
  43:         } 
  44:  
  45:         protected override bool OnWaitForChannel(TimeSpan timeout)
  46:         {
  47:             Console.WriteLine("MyChannelListener<TChannel>.OnWaitForChannel()");
  48:             return this.InnerChannelListener.WaitForChannel(timeout);
  49:         } 
  50:  
  51:         public override Uri Uri
  52:         {
  53:             get 
  54:             {
  55:                 Console.WriteLine("MyChannelListener<TChannel>.Uri"); 
  56:                 return this.InnerChannelListener.Uri;
  57:             } 
  58:  
  59:         } 
  60:  
  61:         protected override void OnAbort()
  62:         {
  63:             Console.WriteLine("MyChannelListener<TChannel>.OnAbort()");
  64:             this.InnerChannelListener.Abort();
  65:         } 
  66:  
  67:         protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
  68:         {
  69:             Console.WriteLine("MyChannelListener<TChannel>.OnBeginClose()");
  70:             return this.InnerChannelListener.BeginClose(timeout, callback, state);
  71:         } 
  72:  
  73:         protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  74:         {
  75:             Console.WriteLine("MyChannelListener<TChannel>.OnBeginOpen()");
  76:             return this.InnerChannelListener.BeginOpen(timeout, callback, state);
  77:         } 
  78:  
  79:         protected override void OnClose(TimeSpan timeout)
  80:         {
  81:             Console.WriteLine("MyChannelListener<TChannel>.OnClose()");
  82:             this.InnerChannelListener.Close(timeout);
  83:         } 
  84:  
  85:         protected override void OnEndClose(IAsyncResult result)
  86:         {
  87:             Console.WriteLine("MyChannelListener<TChannel>.OnEndClose()");
  88:             this.InnerChannelListener.EndClose(result);
  89:         } 
  90:  
  91:         protected override void OnEndOpen(IAsyncResult result)
  92:         {
  93:             Console.WriteLine("MyChannelListener<TChannel>.OnEndOpen()");
  94:             this.InnerChannelListener.EndOpen(result);
  95:         } 
  96:  
  97:         protected override void OnOpen(TimeSpan timeout)
  98:         {
  99:             Console.WriteLine("MyChannelListener<TChannel>.OnOpen()");
 100:             this.InnerChannelListener.Open(timeout);
 101:         }
 102:     }
 103: } 

五、創建Custom Binding Element

我們知道,而Binding由一係列的組成。我們上麵創建的Channel factory和Channel listener需要最終通過對應的BindingElement應用到Binding中才能最終發揮作用。我們就來創建這個BindingElement:MyBindingElement。

   1: namespace Artech.ChannleStackExplore.Channels
   2: {
   3:   public class MyBindingElement:BindingElement
   4:     {
   5:         public override BindingElement Clone()
   6:         {
   7:             return new MyBindingElement();
   8:         } 
   9:  
  10:         public override T GetProperty<T>(BindingContext context)
  11:         {
  12:             return context.GetInnerProperty<T>();
  13:         } 
  14:  
  15:         public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
  16:         {
  17:             Console.WriteLine("MyBindingElement.BuildChannelFactory()");
  18:             return new MyChannelFactory<TChannel>(context) as IChannelFactory<TChannel>;
  19:         } 
  20:  
  21:         public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
  22:         {
  23:             Console.WriteLine("MyBindingElement.BuildChannelListener()");
  24:             return new MyChannelListener<TChannel>(context) as IChannelListener<TChannel>;
  25:         }
  26:     }
  27: }

六、創建Custom Binding

我們進入了最後的階段,創建一個Custom Binding。MyBinding繼承Binding。 在方法中將我們的Binding element(MyBindingElement),連同其他必須的Binding element添加到BindingElementCollection 中。

   1: namespace Artech.ChannleStackExplore.Channels
   2: {
   3:     public class MyBinding:Binding
   4:     {
   5:         public override BindingElementCollection CreateBindingElements()
   6:         {
   7:             BindingElementCollection elemens = new BindingElementCollection();
   8:             elemens.Add(new TextMessageEncodingBindingElement());
   9:             elemens.Add(new MyBindingElement());
  10:             elemens.Add(new HttpTransportBindingElement());
  11:             return elemens.Clone();
  12:         } 
  13:  
  14:         public override string Scheme
  15:         {
  16:             get
  17:             {
  18:                 return "http";
  19:             }
  20:         }
  21:     }
  22: } 

注:對BindElement的組裝可以通過configuration來實現。

七、使用Custom Binding

   1: namespace Server
   2: {
   3:     class Program
   4:     {
   5:         static void Main(string[] args)
   6:         {
   7:             MyBinding binding = new MyBinding();
   8:             IChannelListener<IReplyChannel> channelListener= binding.BuildChannelListener<IReplyChannel>(new Uri("https://127.0.0.1:8888/messagingviabinding"));
   9:             channelListener.Open(); 
  10:  
  11:             while (true)
  12:             {
  13:                 IReplyChannel channel= channelListener.AcceptChannel(TimeSpan.MaxValue);
  14:                 channel.Open();
  15:                 RequestContext context = channel.ReceiveRequest(TimeSpan.MaxValue); 
  16:  
  17:                 Console.WriteLine("Receive a request message:\n{0}", context.RequestMessage);
  18:                 Message replyMessage = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "https://artech.messagingviabinding", "This is a mannualy created reply message for the purpose of testing");
  19:                 context.Reply(replyMessage);
  20:                 channel.Close();
  21:             }
  22:         }
  23:     }
  24: }
   1: namespace Client
   2: {
   3:     class Program
   4:     {
   5:         static void Main(string[] args)
   6:         {
   7:             MyBinding binding = new MyBinding();
   8:             IChannelFactory<IRequestChannel> channelFactory = binding.BuildChannelFactory<IRequestChannel>();
   9:             channelFactory.Open(); 
  10:  
  11:             IRequestChannel channel = channelFactory.CreateChannel(new EndpointAddress("https://127.0.0.1:8888/messagingviabinding"));
  12:             channel.Open(); 
  13:  
  14:             Message requestMessage = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "https://artech.messagingviabinding", "This is a mannualy created reply message for the purpose of testing");
  15:             Message replyMessage = channel.Request(requestMessage);
  16:             Console.WriteLine("Receive a reply message:\n{0}", replyMessage);
  17:             channel.Close();
  18:             channelFactory.Close();
  19:             Console.Read();
  20:         } 
  21:  
  22:     }
  23: } 

wcf2_02_01

wcf2_02_02

通過上麵的輸出結果,你很直觀的了解到了整個程序執行過程中,我們的定義在Channel,Channel factory,Channel listener和Binding element的方法是如何被依次執行的。 

 

WCF後續之旅:
WCF後續之旅(1): WCF是如何通過Binding進行通信的
WCF後續之旅(2): 如何對Channel Layer進行擴展——創建自定義Channel
WCF後續之旅(3): WCF Service Mode Layer 的中樞—Dispatcher
WCF後續之旅(4):WCF Extension Point 概覽
WCF後續之旅(5): 通過WCF Extension實現Localization
WCF後續之旅(6): 通過WCF Extension實現Context信息的傳遞
WCF後續之旅(7):通過WCF Extension實現和Enterprise Library Unity Container的集成
WCF後續之旅(8):通過WCF Extension 實現與MS Enterprise Library Policy Injection Application Block 的集成
WCF後續之旅(9):通過WCF的雙向通信實現Session管理[Part I]
WCF後續之旅(9): 通過WCF雙向通信實現Session管理[Part II]
WCF後續之旅(10): 通過WCF Extension實現以對象池的方式創建Service Instance
WCF後續之旅(11): 關於並發、回調的線程關聯性(Thread Affinity)
WCF後續之旅(12): 線程關聯性(Thread Affinity)對WCF並發訪問的影響
WCF後續之旅(13): 創建一個簡單的WCF SOAP Message攔截、轉發工具[上篇]
WCF後續之旅(13):創建一個簡單的SOAP Message攔截、轉發工具[下篇]
WCF後續之旅(14):TCP端口共享
WCF後續之旅(15): 邏輯地址和物理地址
WCF後續之旅(16): 消息是如何分發到Endpoint的--消息篩選(Message Filter)
WCF後續之旅(17):通過tcpTracer進行消息的路由

 


作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-30 17:33:34

  上一篇:go  Kubernetes Meetup深秋成都行 Ghostcloud精靈雲獲好評如雲
  下一篇:go  WCF後續之旅(3): WCF Service Mode Layer 的中樞—Dispatcher