本文章是由機器翻譯。

地基

使用 「.NET 服務匯流排

Juval Loy

可從 MSDN 程式庫 的程式碼下載
瀏覽線上的程式碼

內容

在 Rescue 轉接服務
轉接服務位址
服務匯流排的繫結
單向的轉接繫結
事件轉接的繫結
轉接服務,為的事件集線器
期待

在.NET 服務匯流排是視為最存取、 功能強大的和有用的新 Windows Azure 定域機組運算 」 開發案。在.NET 服務匯流排是設計解決一些困難的連線能力問題,它也降低技術的進入障礙,並讓主流和例行所使用的進階的通訊案例提供延展性、 可用性及安全性問題的吸引力解決方案。特別是,.NET 服務匯流排位址挑戰的網際網路連線。事實上是很難網際網路連線。通常,服務位於防火牆 (同時軟體及硬體防火牆),背後負載平衡,其位址的是動態和並可以解決只有在區域網路上並無法轉譯為外部位址設定。模擬會將新的維度加入以及與維護跨機器的傳輸工作階段的連線性。這種情況下描繪於 [圖 1

fig01.gif

[圖 1 網際網路連線的挑戰

此外,由於是從網際網路的呼叫端開啟內部網路通常 inadvisable 則企業通常依靠使用周邊的網路,但是又造成增加複雜性和管理多組以及不必要的流量,未經授權的呼叫的用戶端認證的部署。commonplace 的解決方案的靜態 IP 從動態 DNS 網際網路連線通常麻煩,不更新及時實際但擁有延展性及輸送量的含意,而且可能不安全專家所建置,除非。

需要回呼至用戶端服務時,問題被而且用戶端實際上的 [圖 1 鏡像影像的周圍的所有連線問題。並還,回呼 (Callback)、 事件和點對點的呼叫是通常不可或缺的許多從裝載互動式的通訊媒體共用的遊戲的消費者電腦的應用程式部分等,到漫遊使用臨機操作連線,完整的跨內部網路商務對商務應用程式的企業電腦。

在 Rescue 轉接服務

網際網路連線問題在解決方案是簡單,因為它是如此困難,直接連線到在服務的用戶端,則您可以避免這麼做 (至少一開始),並改使用轉接服務。轉送服務都是位於定域機組的工作是協助連線能力轉送用戶端呼叫服務的服務。這樣轉送的解決方案需要用戶端和服務的內部網路允許連線到在的雲],但自定域機組在用戶端和服務構成中性的領土,大部分的環境會允許網際網路時呼叫。

[圖 2]顯示轉接服務的運作方式。

先,服務和用戶端都必須建立連接並轉接服務進行驗證。這時候,轉送也會記錄服務的目前位置,以及如何最佳呼叫回它。當用戶端將呼叫轉接服務時,轉送服務就會轉送服務,呼叫 (用戶端訊息)。

fig02.gif

[圖 2 : 在執行的轉接服務

順序看起來簡單時, 實際上需要相當長的複雜的網路程式設計、 訊息和標準的實用知識、 安全性專業知識,及其他。這類解決方案的只是大部分的應用程式的範圍。這是 Microsoft.NET 服務匯流排用來填滿的間隔。它是現成的轉接服務,裝載,並在 Microsoft 資料中心管理。在.NET 服務匯流排是周邊網路的 Cloud 中的提供單一位置來管理用戶端和服務的認證。在.NET 服務匯流排會是前端服務的結尾 ; 它封裝和隔離服務 lurking 網際網路上的惡意呼叫端負責 repelling 各種時遮蔽的實際的服務識別身份和 true 位置中重新執行攻擊,服務拒絕攻擊。

連線到一般的 Windows Communication Foundation (WCF) 服務] 和 [使用轉送的主要差異服務會隨著周圍裝載。在轉送的情況下服務必須連線到.NET 服務匯流排、 驗證本身,並接聽呼叫來自轉送服務之前,用戶端傳送其要求。這表示您可能必須明確地啟動,主應用程式或使用主應用程式,並且您無法從裝載於 Windows Activation Service (WAS) 中獲益的 NT 服務 (或 IIS) WAS 之後將會啟動主應用程式才是第一個要求進來時,且將永遠不會發生因為主應用程式有沒有連線到.NET 服務匯流排的。

在.NET 服務匯流排支援易記的 WCF 程式設計模型提供一組固定的繫結和行為。和大的以外的程式設計模型的少數稍微 twists,轉接服務的使用不與的不同使用任何其他的 WCF 服務。在.NET 服務匯流排會支援可靠傳訊 」、 「 訊息的安全性及 「 傳輸安全性的核心 WCF] 的功能。雖然,可能會在未來的發行版本中變更,它不支援用戶端服務的交易傳的用在 「 轉接 」 服務。在.NET 服務匯流排也支援兩個其他相關程式設計模型只是的服務端點之外: 訊息佇列和訊息路由。我將提出佇列和因為組合可讓另一個組重要的設計的案例,網際網路連線之外,在未來的專欄路由。

轉接服務位址

之後您可以開啟的帳號與.NET 服務匯流排,您需要使用.NET 服務匯流排管理網站,建立新的解決方案 (請參閱 [圖 3 )。(之前您進一步任何先注意此資料行] 和 [即將發行的資料行所隨附的所有示範都使用 MySolution 做為預留位置方案名稱。若要執行在示範,您必須與.NET 服務匯流排,建立自己的帳戶,並取代您的方案名稱的 MySolution,並提供您的解決方案的認證。若要建立帳號,請移至 servicebus.Windows。net)。

[圖 3] 建立解決方案

解決方案相當於中的一般的網路位址設定電腦或網域名稱以及任何可用的 URI-字串。

像任何其他 WCF 服務每個項轉送的服務必須具有唯一的位址。位址的格式,永遠都是為後面接著任何數目的選擇性的 URI 的基底位址:

[base address]/[optional URI]/.../[optional URI]

基底位址的格式一定被以傳輸結構描述 (然後在 [方案名稱,後面服務匯流排的位址:

[schema]://[solution]/[service bus address]

服務的匯流排位址為:

servicebus.windows.net

結構描述的格式會不 sb、 http 或 https。 以下是一些可能的位址:

sb://MySolution/servicebus.windows.net
sb://MySolution/servicebus.windows.net/MyService
sb://MySolution/servicebus.windows.net/MyService/MyEndpoint
sb://MySolution/servicebus.windows.net/AnythingYouLike

http://MySolution/servicebus.windows.net
https://MySolution/servicebus.windows.net/MySolution/AnythingYouLike

一旦您的服務連線至轉送服務,並啟動它的位址上接聽,沒有其他的服務時,可以聆聽您服務的 URI 範圍的任何其他 URI。

服務匯流排的繫結

在.NET 服務匯流排會提供多個繫結來轉送郵件,但四個主要的繫結我著重在這裡是 TCP 轉送繫結 」、 「 WS 轉送繫結 」、 「 單向的轉送,繫結和 「 繫結,事件轉送 (特別是,NetTcpRelayBinding、 WSHttpRelayBinding、 NetOnewayRelayBinding,以及繫結 NetEventRelayBinding)。

TCP 轉送繫結,是在大多數情況下,涉及所選擇的繫結會轉送網際網路連線。 它會產生最佳的效能與輸送量時最小化服務] 和 [轉接服務的額外負荷。 它支援要求-回覆作業、 單向的作業和全透過轉接服務的甚至雙面回呼。 結構描述,TCP 轉送會永遠使用 sb:

<endpoint
   address  = "sb://MySolution/servicebus.windows.net/..."   binding  = "netTcpRelayBinding"   contract = "..."/>

TCP 轉送繫結需要 TCP 連接埠 808 (或 828) (使用傳輸安全性時要開啟呼叫的 Out]、 [資訊大部分的環境的支援。 TCP 轉送繫結提供無限制的郵件大小 (或至少設定的郵件大小,最多如同一般的 TCP 繫結)。 永遠繫結,TCP 轉送維護傳輸工作階段,以便與工作階段的完整服務,呼叫對相同的 Proxy 通道一定最後到達相同的服務執行個體。 不過,如這個繫結使用二進位 TCP 編碼方式,它並不是互通性 — 它會假設另一端也使用 TCP 轉送繫結。

TCP 轉送繫結提供三種連線模式: 轉送,直接和混合式。 如您在 [圖 4 中所見,您就會設定使用 TcpRelayConnectionMode 列舉] 和 [ConnectionMode 屬性的 NetTcpRelayBindingBase,連線模式。

[圖 4 TCP 轉接的連線模式

public enum TcpRelayConnectionMode
{
   Relayed,
   Direct,
   Hybrid
}
public abstract class NetTcpRelayBindingBase : Binding,...
{
   public TcpRelayConnectionMode ConnectionMode 
   {get;set;}
   //More members
}
public class NetTcpRelayBinding : NetTcpRelayBindingBase
{...}

設定 TcpRelayConnectionMode.relayed 永遠會通過,轉送來決定服務的所有呼叫。 轉送的連線將是您,TCP 轉送繫結的預設模式。

設定 TcpRelayConnectionMode.direct 服務第一次連線至轉送服務驗證本身 (步驟 1 [圖 5 ] 中),然後用戶端連線,並驗證本身 (步驟 2 [圖 5 ] 中)。 不過,這時候轉接服務將會升級連線用戶端與服務,之間的直接連線到告訴用戶端如何到達服務直接 (在 [圖 5] 步驟 3)。 使用的位置,在用戶端可以繼續呼叫服務直接 (步驟 4 [圖 5 ] 中)。

fig05.gif

[圖 5 直接的 TCP 連線

轉接服務將會嘗試升級最直接的連線可以連線,; 也就是,如果用戶端和服務在相同的內部網路的一部分,它將提供用戶端使用 「 好的座標,一樣,如果在同一部電腦上。

如果無法直接連線 (通常是如果轉送服務正確地無法識別服務的位址),在中止連線。 直接的連線服務需要其電腦 (項目可能需要一次性的使用者提示) 上的通訊埠 819 也開啟。

當 TCP 轉送繫結設定 TcpRelayConnectionMode.hybrid 時,通訊就會開始透過轉接服務轉送。 用戶端與服務的直接連線可能是否轉送服務將會升級它直接連線。 否則,它都為轉送。 轉接服務,可以升級導向,即使轉送郵件而不會遺失任何資料。 混合模式應該是透過 TCP 轉送繫結的慣用的連接模式。 不過,它有一個缺點: 在直接和混合模式則需要使用訊息的安全性繫結中,而且您會發現在這個資料行的下一個,郵件安全性會需要額外的組態] 和 [安裝程式。 雖然這些簡單的步驟,它們執行排除混合式為工作選項根據預設,

我已經,提到,但是反白顯示 TCP 轉送繫結支援雙面回呼,轉送到事實上,值得的。 設定 [雙面列印的呼叫,並存取回呼參考等於標準的 TCP 繫結。 目前,TCP 轉送繫結都是在只的轉送繫結支援 (請參閱 [圖 6 ) 的雙面回呼。

fig06.gif

[圖 6 雙工 TCP 轉送回呼

WS 轉送繫結會傳送,及接收透過 HTTP 或 HTTPS) 的互通性的 WCF 訊息。 像一般的 WS 繫結使用文字編碼方式預設的情況下,並使用訊息安全性或可靠的傳訊時將會透過轉送維護傳輸工作階段。 位址,配置會是 http 或 https。

<endpoint   address  = "http://MySolution/servicebus.windows.net/..."   binding  = "wsHttpRelayBinding"   contract = "..."/>

到以及功能使用,WS 轉送繫結 TCP 轉送繫結一樣,除了它支援只能轉送連線。 您應該使用這個繫結,使用 TCP 轉送繫結的 TCP 連接埠封鎖時或當您有交互操作的明確需要。

單向的轉接繫結

單向的轉接的繫結會允許維護在 「 轉接 」 服務,而不是服務本身,緩衝區中傳送其訊息] 和 [更新版本已經的轉送服務會嘗試將訊息傳送到服務用戶端。 若要控制.NET 服務匯流排上的負載,傳送的郵件限於的 64KB (此限制可能會在未來變更)。 可能是使用從服務沒有回應,並事實,單向的轉接的繫結會驗證端點的合約上的所有作業都定義為單向作業。 TCP 和 WS 轉送繫結的情況中,用戶端呼叫轉接服務、 服務本身必須接聽或用戶端會遇到 EndpointNotFoundExcpetion 例外狀況時就像使用非轉送的 WCF (這是大小寫即使在定義為單向作業)。 在單向的轉送,繫結的情況下用戶端可以發出呼叫不論的服務,且有可能甚至無法接聽所有服務。 結果不明服務的狀態時您應該選擇單向的轉接的繫結。 缺點是,用戶端有不保證傳遞的郵件,也沒有任何的保證,分派至服務呼叫的順序。 此外,由於繼承中斷連接本質的單向的轉接的繫結,所以有是永遠不會傳輸工作階段。 只為具有 TCP 及 WS 轉送繫結,有是只有一個服務,監視轉送位址,雖然無法有任何數目的用戶端呼叫該服務。 在的結構描述單向的轉送會永遠使用 sb:

<endpoint   address  = "sb://MySolution/servicebus.windows.net/..."   binding  = "netOnewayrelayBinding"   contract = "..."/>

事件轉接的繫結

事件轉送繫結會為淺,但重要的特製化的單向的轉接的繫結:

public class NetEventRelayBinding : NetOnewayRelayBinding
{...}

它可讓任何數目的服務以監視在轉送服務相同的 URI。 一旦用戶端會將訊息傳送到轉送,所有監視的服務就會收到它。 事實上指定有是用戶端,數目沒有限制此事實提供 N:M 通訊其中 N 和 M 可以是任何自然號碼 (包括零類似 UDP 多點傳送。 因為在特製化,是在服務端,用戶端可以使用單向的轉接的繫結或事件轉送繫結服務必須使用事件轉送繫結時。 另外,與任何其他轉送繫結,不同的是您也可以有巢狀的 URI 上同時的接聽的服務。 與單向的轉送繫結,並不保證順序的訊息或傳送本身。

fig07.gif

[圖 7 事件轉送服務

標準使用事件轉送繫結的案例是事件的最,發行和以 [圖 7 ] 中顯示的訂閱。 現在稱為發行者,在用戶端會呼叫轉送服務現在做為傳送 [事件] 至任何數目的服務的事件集線現在稱為訂閱者。

轉接服務,為的事件集線器

顯示設計 [圖 7 具有外觀的一般用途的 publish-subscribe 模式 (的更多如何實作完整功能的發佈訂閱,請參閱我的文件 」 WCF 的基本功能: 什麼您需要到瞭解關於單向呼叫、 回呼和事件"). 實際上,事件轉送繫結是縮排,提供僅輕量型、 現成定域機組-協助事件通訊群組解決方案,提供執行服務的事件。 加入] 和 [移除訂閱者、 篩選的事件和事件的系統管理支援的功能更強大功能 (以啟用 [同時排入佇列的發行者 」 和 「 佇列的訂閱者]) 的佇列所有需要使用佇列和路由器的後續資料行中,我將討論的。

如果您想要只透過轉接服務執行訂閱者發佈事件 </ a >,再轉接服務視為您的事件集線器就夠了。 不過,您會很快就執行到,不支援的不連續、 作業的層級的事件。 事件會等同至服務的端點 (或) 更特別地是,合約。 訂閱至特定的作業的合約上而非其他服務沒有能力。 這表示訂閱服務仍會接收的事件它可能不在乎只因為它有一個對應的端點。 舉例來說,請參考 IMyEvents 合約:

[ServiceContract]
interface IMyEvents
{
   [OperationContract(IsOneWay = true)]
   void OnEvent1();

   [OperationContract(IsOneWay = true)]
   void OnEvent2(int number);

   [OperationContract(IsOneWay = true)]
   void OnEvent3(int number,string text);
}

如果訂閱者端定義的結束點在下列程式碼中的,訂閱者將的不用說會收到端點的所有呼叫。

<endpoint
   address  = "sb://MySolution/servicebus.windows.net/IMyEvents"
   binding  = "netEventRelayBinding"
   contract = "IMyEvents"
/>

如果訂閱者關心只接收 OnEvent2 作業呼叫,它仍然必須透過事件轉送繫結公開端點、 接收到 OnEvent2,在呼叫,但也 OnEvent1 和 OnEvent3 接收所有不必要的流量並篩選這些內部。 這是直接的結果,在合約 (或結束點) 的訂閱層級的與不會獨立的作業層級。

管理在作業層級的事件,唯一方式,為對應的 URI 不端點的作業。 圖 8 會顯示這類端點的發行者檢視。

[圖 8 定義作業層級的事件

<endpoint name = "OnEvent1"
   address  = "sb://MySolution/servicebus.windows.net/IMyEvents/OnEvent1"
   binding  = "netOnewayBinding"
   contract = "IMyEvents"

/>
<endpoint name = "OnEvent2"
   address  = "sb://MySolution/servicebus.windows.net/IMyEvents/OnEvent2"
   binding  = "netOnewayBinding"
   contract = "IMyEvents"
/>
<endpoint name = "OnEvent3"
   address  = "sb://MySolution/servicebus.windows.net/IMyEvents/OnEvent3"
   binding  = "netOnewayBinding"
   contract = "IMyEvents"
/>

當發行用戶端可以輕易地使用精確端點來引發,特定的事件不是直接設定在訂閱者端。 首先要允許訂閱和取消訂閱個別的事件,而不會影響其他事件處理,在進行中。 第二,訂閱者可能無法開啟使用相同的主機中,因為您會取得任何的所有端點,,它仍會取得所有不必要的事件。 管理作業的層級的事件,唯一方式,為合約,所有針對相同的服務型別上的作業有多個主機。 每個主機將會開啟單一端點對應到特定事件 (作業)。 訂閱或取消訂閱特定事件,在執行階段中,,您必須開啟或關閉,對應的主應用程式。 因為您無法使用的清單,主應用程式 (這會就讓所有開啟的所有端點的主機) 的組態檔中的端點,您必須以程式設計方式加入每個所需的端點特定主應用程式。 如 [圖 9 ] 所示虛擬程式碼中。 [圖 9 ] 中的程式碼會公開給發行者,在 [圖 8 ] 中,端點上設定的。

[圖 9 Equating 作業的事件

class MySubscriber : IMyEvents
{...}

ServiceHost hostEvent1;
ServiceHost hostEvent2;
ServiceHost hostEvent3;

Binding binding = new NetEventRelayBinding();
Uri baseAddress = new Uri("sb://MySolution/servicebus.windows.net/IMyEvents/");

//Subscribing to all events: 
hostEvent1 = new ServiceHost(typeof(MySubscriber),baseAddress);
hostEvent1.AddServiceEndpoint(typeof(IMyEvents),binding,"OnEvent1");
hostEvent1.Open();

hostEvent2 = new ServiceHost(typeof(MySubscriber),baseAddress);
hostEvent2.AddServiceEndpoint(typeof(IMyEvents),binding,"OnEvent2");
hostEvent2.Open();

hostEvent3 = new ServiceHost(typeof(MySubscriber),baseAddress);
hostEvent3.AddServiceEndpoint(typeof(IMyEvents),binding,"OnEvent3");
hostEvent3.Open();


//Unsubscribe event 2: 
hostEvent2.Close();

不過的這類的方法是冗長乏味,重複性和容易發生錯誤。 它也會緊密結合事件合約。 若要簡化,自動化],並在我撰寫的協助程式主應用程式如 [圖 10 ] 中所示的 EventRelayHost 這個程式設計模型的分離。 EventRelayHost 所有的建構函式需要至少一個使用基底位址 (與一般主機基底位址是選擇性)。

[圖 10 EventRelayHost

public class EventRelayHost 
{
   public EventRelayHost(Type serviceType,string baseAddress);
   public EventRelayHost(Type serviceType,string[] baseAddresses);

   public void SetBinding(NetEventRelayBinding binding);
   public void SetBinding(string bindingConfigName)

   public void Subscribe();
   public void Subscribe(Type contractType);    
   public void Subscribe(Type contractType,string operation)

   public void Unsubscribe();        
   public void Unsubscribe(Type contractType); 
   public void Unsubscribe(Type contractType,string operation);

   public void Abort();   
   //More members
}

您也可以提供 EventRelayHost,與透過 SetBinding 方法所使用繫結。 EventRelayHost 會預設為一個 NetEventRelayBinding 的純文字的執行個體中。 在訂閱和取消訂閱方法運作非常有很像一般主應用程式的 [開啟舊檔] 及 [關閉] 方法。 您可以訂閱 (或取消訂閱) 的服務型別所支援的所有服務合約的所有事件,在特定的服務合約上的所有事件或特定的事件特定的服務合約上作業。 最後,您可以呼叫中止以中止處理正在進行的所有事件,並 ungracefully 關閉所有的主機。 您可以看到 [圖 11 ] 中 EventRelayHost 的實作。

[圖 11] 實作 EventRelayHost

//Partial listing without error handling and security 
public class EventRelayHost
{
   Dictionary<Type,Dictionary<string,ServiceHost>> m_Hosts = 
                            new Dictionary<Type,Dictionary<string,
                                                  ServiceHost>>();
   Type m_SericeType;
   string[] m_BaseAddresses;

   public void Subscribe(Type contractType,string operation)
   {
      m_Hosts[contractType] = new Dictionary<string,ServiceHost>();
      List<Uri> baseAddressesList = new List<Uri>();
      foreach(string address in m_BaseAddresses)
      {
         baseAddressesList.Add(new Uri(address + contractType));
      }
      m_Hosts[contractType][operation] = 
                        new ServiceHost(m_SericeType, 
                        baseAddressesList.ToArray());
      NetEventRelayBinding binding = new NetEventRelayBinding();
      m_Hosts[contractType][operation].
                               AddServiceEndpoint(contractType,
                                            binding,operation);

      m_Hosts[contractType][operation].Open();
   }
   public void Unsubscribe(Type contractType,string operation)
   {
      m_Hosts[contractType][operation].Close();
   }   
   //More members
}

EventRelayHost 維護的字典每個事件的服務合約的對應型別對應每個作業使用者專用的服務主機的另一個字典。 在訂閱的方法會開啟該主機,並將為每個基底位址的端點加入。 訂閱附加為每個端點的位址,合約的型別] 和 [作業名稱。 沒有在組態檔不需要使用 EventRelayHost 時,而 [圖 11 ] 中的程式碼會縮減為。

EventRelayHost host = new EventRelayHost(typeof(MyService),                                                                         "sb://MySolution/servicebus.windows.net/...");

host.Subscribe();
...
host.Unsubscribe(typeof(IMyEvents),"OnEvent2");

雖然 EventRelayHost 簡化了在訂閱者端,用戶端現在必須維護為事件端點的多個 Proxy。 為了達到我寫了 EventRelayClientBase <t>,宣告如 [圖 12 ] 中。

[圖 12 EventRelayClientBase <t>

public abstract class EventRelayClientBase<T> : IDisposable where T : class
{
   public event EventHandler Closed;  
   public event EventHandler Opened;  

   public CommunicationState State 
   {get;}

   public EventRelayClientBase(string solutionBaseAddress);
   public EventRelayClientBase(string solutionBaseAddress,
                               NetEventRelayBinding binding)

   public void Open();
   public void Close();
   public void Abort();

   public T Channel
   {get;}
   //More members  
}

若要將 EventRelayClientBase <T> 只從它衍生像一般的 ClientBase <T>,我一樣在 [圖 13 .

[圖 13 使用 EventRelayClientBase <t>

class MyEventsProxy : EventRelayClientBase<IMyEvents>,IMyEvents
{
   public MyEventsProxy(string baseAddress) : base(baseAddress)
   {}

   public void OnEvent1()
   {
      Channel.OnEvent1();
   }
   public void OnEvent2(int number)
   {
      Channel.OnEvent2(number);
   }
   public void OnEvent3(int number,string text)
   {
      Channel.OnEvent3(number,text);
   }
}

EventRelayClientBase <t> 提供 quasi-support ICommunicationObject 的狀態,並狀態變更的通知]。 在一般的 Proxy 不像 EventRelayClientBase <t> 會需要訂閱者的基底位址。 到該的位址,它附加合約名稱] 和 [作業名稱以符合 EventRelayHost 所開啟的端點。 如同在的 EventRelayHost 沒有必要的用戶端組態檔案。 雖然 EventRelayClientBase <t> 看起來為單一的 Proxy 用戶端,它是彙總的 Proxy,它可以維持在訂閱者端上的端點每一個 Proxy。

[圖 14 ] 所示,EventRelayClientBase <t> 會有對應的作業的 T 的執行個體字典 — 事件服務合約,提供型別參數。 當用戶端會開啟 EventRelayClientBase <t> 時, 它會使用反映 (Reflection) 取得的所有事件作業集合。 為每個作業,它合約名稱和 (以產生端點位址),作業名稱,附加到基底位址,然後使用通道 Factory,來建立相符的 Proxy 中。

[圖 14] 實作 EventRelayClientBase <t>

//Partial listing without error handling and state management
public abstract class EventRelayClientBase<T> : IDisposable where T : class
{
   readonly string BaseAddress;
   Dictionary<string,T> m_Proxies = new Dictionary<string,T>();
   public CommunicationState State 
   {get;private set;}

   public void Open()
   {
      Binding binding = new NetOnewayRelayBinding();
      MethodInfo[] methods = typeof(T).GetMethods(...);
      foreach(MethodInfo method in methods)
      {
         EndpointAddress address = 
                     EndpointAddress(new Uri(BaseAddress+typeof(T) +
                                                       method.Name));
         ChannelFactory<T> factory = new ChannelFactory<T>(binding,
                                                          address);
         m_Proxies[method.Name] = factory.CreateChannel();
         ICommunicationObject proxy = m_Proxies[method.Name] 
                                    as ICommunicationObject;
         proxy.Open();
      }
      State = CommunicationState.Opened;
   }
   public T Channel
   {
      get
      {
         if(State != CommunicationState.Opened)
         {
            Open();
         }
         StackFrame frame = new StackFrame(1);
         return m_Proxies[frame.GetMethod().Name];
      }
   }
   public void Close()
   {
      foreach(ICommunicationObject proxy in m_Proxies.Values)
      {
         proxy.Close();
      }
   }
   public void Abort()
   {
      foreach(ICommunicationObject proxy in m_Proxies.Values)
      {
         proxy.Abort();
      }
   }
   //More members
}

藉由存取堆疊框架,取得呼叫作業的名稱和使用,做為索引鍵從字典查詢正確的 Proxy,則通道屬性會傳回正確的 Proxy。關閉 EventRelayClientBase <t> 關閉它所管理的所有 Proxy。

期待

WCF 也會提供 [BasicHttpRelayBinding 」、 「 WebHttpRelayBinding 」、 「 WS2007HttpRelayBinding 和 「 WS2007FederationHttpRelayBinding。其名稱表示,這些繫結是一般的 WCF 繫結的轉送的對等用法。此外,WCF 會提供 NetTcpContextRelayBinding、 BasicHttpRelayContextBinding 和 WebHttpRelayContextBinding。這些都是衍生自其對應的內容繫結會轉送繫結,但加入對內容通訊協定的支援。

安全性也會是一個問題。同時用戶端服務應該自行驗證轉送的服務和服務防止用戶端上傳送郵件。我將討論服務匯流排的安全性,以及在全新佇列] 和 [我的下一個資料行中的路由。

您問題或意見寄至mmnet30@Microsoft.com.

Juval Lowy 是一個軟體架構設計人員使用 IDesign 提供 WCF 訓練和架構諮詢。他的最新著作都有 Programming WCF Services 2nd Edition (O ' Reilly,2008)。他也是 Microsoft 地區主管,Silicon Valley 的。在 Juval 的連絡人www.idesign。net.