程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 《WCF技術內幕》39:第2部分_第7章_通道管理器:通道工廠和本章小結

《WCF技術內幕》39:第2部分_第7章_通道管理器:通道工廠和本章小結

編輯:關於.NET

發送者:通道工廠

發送者使用通道工廠來創建通道。它們和通道偵聽器的許多特性相似,但是 不同的是它們駐留在發送者內部,而且不需要從連接上偵聽消息。它們會通過 CreateChannel方法創建符合要求的連接通道而不是消極等待消息到來。和通道 偵聽器一樣,通道工廠也是根據它們創建的通道功能來分類的。

實際上,這意味著每個傳輸通道都會有一個與之關聯的通道工廠,比如支持 WS-*協議的通道。和通道偵聽器一樣,用戶代碼無法直接實例化通道工廠,需要 借助於Binding(你會在第8章裡看到詳細的介紹)。通道工廠類型都繼承自 ChannelManagerBase。而類型層次的其它部分則不相同。本節裡,我們會先研究 一下通道工廠裡不同的類型,然後會創建一個自定義通道工廠來繼續學習我們的 DelegatorChannel例子。

IChannelFactory接口

所有的通道工廠都繼承了IChannelFactory接口。這個接口實現了 ICommunicationObject接口,因此可以強制它的繼承者實現通道狀態機。當然還 有就是暴露與通道和通道偵聽器裡類似的一個查詢機制。代碼如下所示:

public interface IChannelFactory : ICommunicationObject  {
       T GetProperty<T>() where T: class;
}

IChannelFactory<TChannel>接口

所有的通道工廠也都實現了IChannelFactory<TChannel>接口。這個接 口繼承自IChannelFactory,所以它比IChannelFactory的用處更廣。 IChannelFactory<TChannel>定義了2個成員,如下所示:

public interface IChannelFactory<TChannel> :  IChannelFactory {
       TChannel CreateChannel(EndpointAddress to);
       TChannel CreateChannel(EndpointAddress to, Uri  via);
}

CreateChannel方法包含2個參數。它們是EndpointAddress和Uri類型。在運 行時,這些參數會序列化到消息裡,via參數就是通道要嘗試連接的地址,to是 發送消息的地址。中間可能經過消息的中轉(第2章裡曾經講到)。

ChannelFactoryBase類型

通道工廠簡介繼承了抽象類型ChannelFactoryBase。概念上,它的作用與通 道偵聽器裡使用的ChannelListenerBase類型一樣。換句話說, ChannelListenerBase類型也提供了一種自定義打開、關閉、發送和接受消息超 時屬性的方式。它的對象模型如下所示:

public abstract class ChannelFactoryBase :  ChannelManagerBase,
                                             IChannelFactory {
  protected ChannelFactoryBase();
  protected ChannelFactoryBase(IDefaultCommunicationTimeouts  timeouts);
  // IChannelFactory implementation
  public virtual T GetProperty<T>() where T: class;
  // CommunicationObject implementation
  protected override void OnAbort();
  protected override IAsyncResult OnBeginClose(TimeSpan  timeout,
                                                 AsyncCallback callback,
                                                 Object state);
  protected override void OnClose(TimeSpan timeout);
  protected override void OnEndClose(IAsyncResult result);
  protected override TimeSpan DefaultCloseTimeout { get; }
  protected override TimeSpan DefaultOpenTimeout { get; }
  // ChannelManagerBase implementation
  protected override TimeSpan DefaultReceiveTimeout { get; }
  protected override TimeSpan DefaultSendTimeout { get; }
}

ChannelFactoryBase<TChannel>類型

ChannelFactoryBase<TChannel>類型繼承了ChannelFactoryBase 類型 ,而且實現了IChannelFactory<TChannel>接口。它也是通道工廠類型的 基類。更進一步說,這個類型維護和控制通道的創建狀態。(想一下本章前面“ 通道管理器的概念”一節。)ChannelFactoryBase<TChannel>的對象模型 如下:

public abstract class ChannelFactoryBase<TChannel>  : ChannelFactoryBase,
     IChannelFactory<TChannel> {
  // calls the other constructor, passing null as  argument
  protected ChannelFactoryBase();
  // creates an object that manages the channels
  protected ChannelFactoryBase(IDefaultCommunicationTimeouts  timeouts);
  // IChannelFactory<TChannel> implementation
  public TChannel CreateChannel(EndpointAddress address);
  public TChannel CreateChannel(EndpointAddress address, Uri  via);
  // Extensibility point for IChannelFactory<TChannel>  implementation
  protected abstract TChannel OnCreateChannel(EndpointAddress  address, Uri via);
  // CommunicationObject implementation: changes state
  // of the channels it has created
  protected override void OnAbort();
  protected override IAsyncResult OnBeginClose(TimeSpan  timeout, AsyncCallback callback,
object state);
  protected override void OnClose(TimeSpan timeout);
  protected override void OnEndClose(IAsyncResult result);
  // helper method that checks the State to see if  the
  // channel factory can create channels  (CommunicationState.Opened)
  protected void ValidateCreateChannel();
}

ChannelFactoryBase<TChannel>的構造函數實例化了一個對象,這個 對象可以保存工廠裡創建的通道對象的引用。當 ChannelFactoryBase<TChannel> 對象關閉或者終止的時候,這個對象可 以確保引用的通道狀態機與ChannelFactoryBase<TChannel>對象狀態一致 。這些代碼確保狀態改變發生在ChannelFactoryBase<TChannel> 裡 CommunicationObject的實現裡。

ChannelFactoryBase<TChannel>另外一個有趣的地方就是 ValidateCreateChannel 方法。這個方法僅僅是為了確保對象的狀態是 CommunicationState.Opened。如果狀態不是,這個方法就會拋出一個 InvalidOperationException異常。兩個CreateChannel方法都會調用這個方法來 確保通道工廠處於正確的狀態。

創建自定義通道工廠

既然已經學習了通道工廠裡重要的相關類型,現在我們來創建一個自定義通 道工廠,繼續完成我們的DelegatorChannel例子。和前面的 DelegatorChannelListener<TShape>例子類似,我們的通道工廠必須可以 創建任何形狀的通道。因此,我們的通道工廠必須使用泛型,如下所示:

internal sealed class  DelegatorChannelFactory<TShape> :
     ChannelFactoryBase<TShape> {
  // reference the next channel factory in the stack
  IChannelFactory<TShape> _innerFactory;
  // the String to print to the console
  String _consolePrefix = "FACTORY:  DelegatorChannelFactory";
  // ctor that builds the next channel factory in the  stack,
  // then assigns the _innerFactory member variable
  internal DelegatorChannelFactory(BindingContext context) {
     PrintHelper.Print(_consolePrefix, "ctor");
     this._innerFactory =  context.BuildInnerChannelFactory<TShape>();
  }
  // instantiates and returns a DelegatorChannel that
  // references another channel
  private TShape WrapChannel(TShape innerChannel) {
     if(innerChannel == null) {
       throw new ArgumentNullException("innerChannel cannot  be null",
         "innerChannel");
     }
     if(typeof(TShape) == typeof(IOutputChannel)) {
       return (TShape)(Object) new  DelegatorOutputChannel<IOutputChannel>
         (this, (IOutputChannel)innerChannel, "SEND");
     }
     if(typeof(TShape) == typeof(IRequestChannel)) {
       return (TShape)(Object) new  DelegatorRequestChannel
         (this, (IRequestChannel)innerChannel,  "SEND");
     }
     if(typeof(TShape) == typeof(IDuplexChannel)) {
       return (TShape)(Object) new  DelegatorDuplexChannel
         (this, (IDuplexChannel)innerChannel, "SEND");
     }
     if(typeof(TShape) == typeof(IOutputSessionChannel))  {
       return (TShape)(Object) new  DelegatorOutputSessionChannel
         (this, (IOutputSessionChannel)innerChannel,  "SEND");
     }
     if(typeof(TShape) == typeof(IRequestSessionChannel))  {
       return (TShape)(Object) new  DelegatorRequestSessionChannel
         (this, (IRequestSessionChannel)innerChannel,  "SEND");
     }
     if(typeof(TShape) == typeof(IDuplexSessionChannel))  {
       return (TShape)(Object) new  DelegatorDuplexSessionChannel
         (this, (IDuplexSessionChannel)innerChannel,  "SEND");
     }
     // cannot wrap this channel
     throw new ArgumentException(String.Format("invalid  channel shape
       passed:{0}", innerChannel.GetType()));
  }
  // uses the _innerFactory member variable to build a  channel
  // then wraps it and returns the wrapped channel
  protected override TShape OnCreateChannel(EndpointAddress  address,
     Uri via) {
     // create and return the channel
     PrintHelper.Print(_consolePrefix, "OnCreateChannel");
     TShape innerChannel = this._innerFactory.CreateChannel (address, via);
     return WrapChannel(innerChannel);
  }
  protected override IAsyncResult OnBeginOpen(TimeSpan  timeout,
                                                AsyncCallback callback,
                                                Object state) {
     PrintHelper.Print(_consolePrefix, "OnBeginChannel");
     return this._innerFactory.BeginOpen(timeout, callback,  state);
  }
  protected override void OnAbort() {
     base.OnAbort();
     PrintHelper.Print(_consolePrefix, "OnAbort");
  }
  protected override void OnClose(TimeSpan timeout) {
     base.OnClose(timeout);
     PrintHelper.Print(_consolePrefix, "OnClose");
  }
  protected override void OnEndOpen(IAsyncResult result) {
     PrintHelper.Print(_consolePrefix, "OnEndOpen");
     this._innerFactory.EndOpen(result);
  }
  protected override void OnOpen(TimeSpan timeout) {
     PrintHelper.Print(_consolePrefix, "OnOpen");
     this._innerFactory.Open(timeout);
  }
  public override T GetProperty<T>() {
     PrintHelper.Print(_consolePrefix, "GetProperty<" +  typeof(T).Name +
       ">");
     return this._innerFactory.GetProperty<T>();
  }
}

定義上來看,DelegatorChannelFactory<TShape>與 DelegatorChannelListener<TShape> 很相似,它定義了一個私有的 WrapChannel方法,可以把一個通道包裝為特定的形狀,然後返回。當然也定義 了另外幾個方法,這些方法可以把狀態轉換傳遞給成員變量innerFactory的。

本章小結

WCF 類型通過通道工廠和通道偵聽器來創建通道。通道偵聽器負責偵聽可用 的連接。通道工廠和通道偵聽器的架構模型與伯克利的Sockets API十分相似, 和通道一樣,通道工廠和通道偵聽器也是在運行時組裝到堆棧的,並且堆棧裡的 每個通道偵聽器或通道工廠都負責創建一個通道。另外就是傳輸通道工廠或者通 道偵聽器必須位於堆棧的底部。此外,用戶代碼不能直接實例化通道偵聽器和通 道工廠。這些工作有BindingElement完成。Binding和BindingElement對象會在 下一章裡講到,而且作為總結部分,你會看到我們定義的DelegatorChannel 通 道、以及DelegatorChannelListener<TShape> 和 DelegatorChannelFactory<TShape>類型。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved