使用行為來設定與擴充執行階段
行為讓您能在 Windows Communication Foundation (WCF) 用戶端和服務應用程式中修改預設行為,並且新增可檢查與驗證服務組態的自訂延伸,或是修改執行階段行為。本主題會說明行為介面、如何實作這些介面,以及如何透過程式設計方式或組態檔來將它們新增到服務描述 (在服務應用程式中) 或端點 (在用戶端應用程式中)。如需使用系統提供行為的詳細資訊,請參閱指定服務執行階段行為和指定用戶端執行階段行為。
行為
行為類型會先新增到服務或服務端點描述物件 (分別在服務或用戶端上),Windows Communication Foundation (WCF) 才能使用這些物件來建立執行 WCF 服務或 WCF 用戶端的執行階段。當在執行階段建構程序期間呼叫這些行為之後,這些行為即可存取可修改由合約、繫結及位址所構成之執行階段的執行階段屬性和方法。
行為方法
所有的行為方法都有 AddBindingParameters 方法、ApplyDispatchBehavior 方法、Validate 方法,以及例外的 ApplyClientBehavior 方法:因為 IServiceBehavior 無法在用戶端中執行,因此它不會實作 ApplyClientBehavior。
- 使用 AddBindingParameters 方法來修改自訂物件,或將其加入至自訂繫結可在執行階段建構時存取以供自己使用的集合中。例如,在這種情況下,通道開發人員不知道實際影響通道建置方式的保護需求指定方式。
- 使用 Validate 方法來檢查描述樹狀目錄和對應的執行階段物件,以確定該物件符合一些準則。
- 使用 ApplyDispatchBehavior 和 ApplyClientBehavior 方法來檢查描述樹狀目錄,以及修改服務或用戶端上之特定範圍的執行階段。您也可以插入擴充物件。
注意: 雖然在這些方法中有提供描述樹狀目錄,但它僅供檢查用途。如果描述樹狀目錄遭到修改,該行為便屬於未定義的。
您可以修改的屬性及可以實作的自訂介面,將透過服務和用戶端執行階段類別來存取。這些服務類型是 DispatchRuntime 與 DispatchOperation 類別。用戶端類型則是 ClientRuntime 與 ClientOperation 類別。ClientRuntime 與 DispatchRuntime 類別分別是存取全用戶端及全服務執行階段屬性和擴充集合的擴充性進入點 (Entry Point)。同樣地,ClientOperation 與 DispatchOperation 類別會分別公開 (Expose) 用戶端作業及服務作業執行階段屬性和擴充集合。不過,您可以從作業執行階段物件存取範圍更廣的執行階段物件,或是在需要時反向執行。
注意: |
---|
如需可用來修改用戶端執行之行為的執行階段屬性與擴充類型的詳細討論,請參閱擴充用戶端。如需可用來修改服務發送器執行之行為的執行階段屬性與擴充類型的詳細討論,請參閱擴充發送器。 |
大多數 WCF 使用者都不會與執行階段直接互動,而是在組態檔中的類別或行為上使用核心程式設計模型建構,例如端點、合約、繫結、位址及行為屬性。這些建構組成「描述樹狀目錄」(Description Tree),也就是在建構執行階段以支援此描述樹狀目錄所描述之服務或用戶端的完整規格。
WCF 中的行為分為四種:
- 服務行為 (IServiceBehavior 類型) 讓整個服務執行階段 (包括 ServiceHostBase) 能夠進行自訂。
- 端點行為 (IEndpointBehavior 類型) 讓服務端點及其關聯的 EndpointDispatcher 物件能夠進行自訂。
- 合約行為 (IContractBehavior 類型) 讓 ClientRuntime 與 DispatchRuntime 類別能夠分別在用戶端及服務應用程式中進行自訂。
- 作業行為 (IOperationBehavior 類型) 同樣地讓 ClientOperation 與 DispatchOperation 類別能在用戶端及服務上進行自訂。
將這些行為新增到各種描述物件的作業,可以透過實作自訂屬性、使用應用程式組態檔來完成,或是將這些行為直接新增到適當描述物件的行為集合中。不過,在呼叫 ServiceHost 或 ChannelFactory 上的 System.ServiceModel.ICommunicationObject.Open 之前,這些行為一定要先新增到服務描述或服務端點描述物件。
行為範圍
這四個行為類型都會分別對應到執行階段存取的特定範圍。
服務行為
實作 IServiceBehavior 的服務行為,是您用來修改整個服務執行階段的主要機制。將服務行為新增到服務時可使用三種機制。
在服務類別上使用屬性。當已建構 ServiceHost 時,ServiceHost 實作 (Implementation) 會使用反映 (Reflection) 來找出該服務類型上的一組屬性。如果其中任何一個屬性是 IServiceBehavior 的實作,這組屬性便會新增到 ServiceDescription 上的行為集合中。這樣便可讓這些行為參與建構服務執行階段的程序。
以程式設計方式將行為新增到 ServiceDescription 上的行為集合中。運用下列幾行程式碼即可達成這點:
ServiceHost host = new ServiceHost(/* Parameters */); host.Description.Behaviors.Add(/* Service Behavior */);
實作會擴充組態的自訂 BehaviorExtensionElement。這樣便可從應用程式組態檔使用服務行為。
有關 WCF 中服務行為的範例包括 ServiceBehaviorAttribute 屬性、ServiceThrottlingBehavior 及 ServiceMetadataBehavior 行為。
合約行為
實作 IContractBehavior 介面的合約行為,可用於擴充整個合約的用戶端與服務執行階段。
將合約行為新增到合約時可以使用兩種機制。第一種機制是建立要在合約介面上使用的自訂屬性。當合約介面傳遞至 ServiceHost 或 ChannelFactory 時,WCF 便會檢查該介面上的屬性。如果其中任何一個屬性是 IContractBehavior 的實作,這些屬性便會新增到為該介面建立之 System.ServiceModel.Description.ContractDescription 上的行為集合中。
您也可以在自訂合約行為屬性上實作 System.ServiceModel.Description.IContractBehaviorAttribute。在此情況下,將依套用對象產生類似下列的行為:
•合約介面。在此情況下,行為會套用至任何端點中的所有該類型合約,而且 WCF 會忽略 System.ServiceModel.Description.IContractBehaviorAttribute.TargetContract 屬性的值。
•服務類別。在此情況下,行為只會套用至其中合約為 TargetContract 屬性值的端點。
•回呼類別。在此情況下,行為會套用至雙工用戶端的端點,而且 WCF 會忽略 TargetContract 屬性的值。
第二種機制是將行為新增至 ContractDescription 上的行為集合。
有關在 WCF 中的合約行為範例包括 System.ServiceModel.DeliveryRequirementsAttribute 屬性。如需詳細資訊和範例,請參閱參考主題。
端點行為
實作 IEndpointBehavior 的端點行為,是您用來針對特定端點修改整個服務或用戶端執行階段的主要機制。
將端點行為新增到服務時可以使用兩種機制。
- 將行為新增到 Behaviors 屬性。
- 實作會擴充組態的自訂 BehaviorExtensionElement。
如需詳細資訊和範例,請參閱參考主題。
作業行為
實作 IOperationBehavior 介面的作業行為,可用來擴充每個作業的用戶端與服務執行階段。
將作業行為新增到作業時可以使用兩種機制。第一種機制是建立要用於建立作業模型之方法的自訂屬性。當作業新增到 ServiceHost 或 ChannelFactory 時,WCF 會將任何 IOperationBehavior 屬性都新增到為該作業建立之 OperationDescription 上的行為集合。
第二種機制是將行為直接新增至已建構 OperationDescription 上的行為集合中。
有關 WCF 中的作業行為範例包括 OperationBehaviorAttribute 和 TransactionFlowAttribute。
如需詳細資訊和範例,請參閱參考主題。
使用組態來建立行為
服務行為、端點行為以及合約行為都可以設計成透過程式碼或使用屬性來加以指定;只有服務行為和端點行為可以使用應用程式或 Web 組態檔來加以設定。使用屬性公開行為,可讓開發人員在編譯時期指定在執行階段時所無法新增、移除或修改的行為。這種做法往往適用於正確服務作業一定需要的行為 (例如,System.ServiceModel.ServiceBehaviorAttribute 屬性的交易相關參數)。使用組態公開行為,可讓開發人員將這些行為的規格和組態留給部署該服務的人員來決定。這種做法適用於屬於選擇性元件或其他部署特定組態的行為,例如是否要向服務公開中繼資料,或是服務的特定授權組態。
注意: |
---|
您也可以使用支援組態強制公司應用程式原則的行為,使用方法是將這些行為插入 machine.config 組態檔,並鎖定這些項目。如需範例與描述,請參閱 HOW TO:鎖定企業的端點。 |
若要使用組態公開行為,開發人員必須建立 BehaviorExtensionElement 的衍生類別 (Derived Class),然後再向組態註冊該延伸。
下列程式碼範例會示範 IEndpointBehavior 如何實作 BehaviorExtensionElement:
為了讓組態系統載入自訂 BehaviorExtensionElement,此項目必須註冊為延伸。下列程式碼範例顯示了前述端點行為的組態檔:
其中,Microsoft.WCF.Documentation.EndpointBehaviorMessageInspector
是行為延伸型別,而 HostApplication
是類別已在其中完成編譯的組件 (Assembly) 名稱。
評估順序
System.ServiceModel.ChannelFactory 和 System.ServiceModel.ServiceHost 會負責從程式設計模型及描述來建置執行階段。正如先前所述,行為會作用於位在服務、端點、合約及作業時的建置程序。
ServiceHost 會依照下列順序來套用行為:
- 合約
- 作業
- 端點
- 服務
在任何行為集合內,並不會保證任何順序。
ChannelFactory 會依照下列順序來套用行為:
- 合約
- 端點
- 作業
同樣地,在任何行為集合內,並不會保證任何順序。
以程式設計方式來新增行為
在服務應用程式中 System.ServiceModel.Description.ServiceDescription 的屬性,絕對不能在呼叫 System.ServiceModel.ServiceHostBase 上的 System.ServiceModel.Channels.CommunicationObject.OnOpening 方法之後遭到修改。有些方法在通過該點後若遭到修改,就會擲回例外狀況,這些方法包括 System.ServiceModel.ServiceHostBase.Credentials 屬性,以及在 ServiceHostBase 與 System.ServiceModel.ServiceHost 上的 AddServiceEndpoint 方法。其他方法可讓您加以修改,但結果仍不明確。
同樣地,您不可以在呼叫 System.ServiceModel.ChannelFactory 上的 OnOpening 之後修改用戶端上的 System.ServiceModel.Description.ServiceEndpoint 值。如果 System.ServiceModel.ChannelFactory.Credentials 屬性在通過該點之後遭到修改,它便會擲回例外狀況,不過其他用戶端描述值在遭到修改時並不會造成錯誤。不過產生結果將會是未定義的。
無論在是服務或是用戶端,我們的建議做法是在呼叫 System.ServiceModel.Channels.CommunicationObject.Open 之前先修改此描述。
行為屬性的繼承規則
這四種行為都可以使用屬性 (服務行為與合約行為) 來填入。由於屬性是定義在 Managed 物件與成員上,而 Managed 物件與成員會支援繼承 (Inheritance),所以這時必須定義行為屬性在繼承內容中的運作方式。
在高層級的規則是指針對特定範圍 (例如,服務、合約或作業) 的規則,而繼承階層架構 (Inheritance Hierarchy) 中的所有行為屬性是指針對該範圍所套用的行為屬性。如果這時出現兩個相同型別的行為屬性,將只套用最末層衍生型別。
服務行為
對於特定的服務類別,將套用該類別及其父代 (Parent) 上的所有服務行為屬性。如果相同型別的屬性套用在繼承階層架構的多個位置,這時會使用最具衍生性的型別。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
[AspNetCompatibilityRequirementsAttribute(
AspNetCompatibilityRequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class A { /* … */ }
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class B : A { /* … */}
例如,在上述範例中,服務 B 最後產生 Single 的 InstanceContextMode、Allowed 的 AspNetCompatibilityRequirementsMode 模式,以及 Single 的 ConcurrencyMode。由於服務 B 上的 ServiceBehaviorAttribute 屬性比服務 A 上的相同屬性「更具衍生性」,所以 ConcurrencyMode 會是 Single。
合約行為
對於指定的合約,將套用該介面及其父代上的所有合約行為屬性。如果相同型別的屬性套用在繼承階層架構的多個位置,這時會使用最具衍生性的型別。
作業行為
如果指定的作業沒有覆寫現有的抽象或虛擬作業,就不會套用任何繼承規則。
如果作業確實覆寫了現有的作業,這時將套用該作業及其父代上的所有作業行為屬性。如果相同型別的屬性套用在繼承階層架構的多個位置,這時會使用最具衍生性的型別。