標籤:
摘要:概覽 Windows Communication Foundation (WCF) 體繫結構及其主要概念。程式碼範例示範 WCF 約定、終結點和行為。本頁內容
簡介
WCF 基礎
程式碼範例
小結
簡介
本文檔提供 Windows Communication Foundation (WCF) 體繫結構的概覽。本文旨在闡釋 WCF 中的主要概念以及它們如何協調工作。還有幾個程式碼範例對這些概念進行深入闡釋,但代碼不是本文檔的重點。
本文檔下面的部分分為以下兩個主要內容:
返回頁首
WCF 基礎
WCF 服務是一個公開終結點 集合的程式。每個終結點都是一個與外界通訊的入口。
用戶端是一個與一個或多個終結點交換訊息的程式。用戶端還可以公開一個終結點,從而以雙工訊息交換的模式從服務接收訊息。
以下部分更詳細地描述了這些基礎。
終結點
一個服務端點具有一個地址、一個綁定 和一個約定。
終結點的地址是終結點駐留的網路地址。EndpointAddress 類表示一個 WCF 端點位址。
終結點的綁定指定終結點與外界通訊的方式,包括傳輸協議(例如,TCP、HTTP)、編碼(例如,文本、二進位檔案)以及安全要求(例如,SSL、SOAP 訊息安全)等。Binding 類表示 WCF 綁定。
終結點的約定指定終結點通訊的內容,它本質上是操作中有組織的訊息集合,這些操作具有基本的訊息交換模式 (MEPs),如單工、雙工,以及請求/應答。ContractDescription 類表示 WCF 約定。
ServiceEndpoint 類表示終結點,它具有一個 EndpointAddress、一個綁定以及一個 ContractDescription,分別對應於終結點的地址、綁定和約定(參見圖 1)。
圖 1. 每個服務的終結點包含一個 EndpointAddress、一個綁定以及一個由 ContractDescription 表示的約定。
EndpointAddress
EndpointAddress 實際上是一個 URI、一個標識和一個可選標題的集合, 2 所示。
終結點的安全標識通常就是它的 URI;然而在進階方案中,可以使用 Identity 地址屬性獨立於 URI 來顯式設定標識。
可選標題用於提供除終結點 URI 外的其他定址資訊。例如,地址標題對於區分共用相同地址 URI 的多個終結點很有用。
圖 2. EndpointAddress 包含一個 URI,AddressProperties 包含一個標識和一個 AddressHeaders 集合。
綁定
綁定具有名稱、命名空間,以及一個可編寫的繫結元素的集合(圖 3)。綁定的名稱和命名空間在服務的中繼資料中唯一標識該綁定。每個繫結元素都描述終結點與外界通訊的方式 的一個方面。
圖 3. 綁定類及其成員
例如,圖 4 顯示一個包含三個繫結元素的繫結元素集合。每個繫結元素的存在都描述與終結點通訊的方式 的一部分。TcpTransportBindingElement 表示終結點將使用 TCP 作為傳輸協議與外界通訊。ReliableSessionBindingElement 表示終結點使用可靠的訊息處理來提供訊息傳遞保證。SecurityBindingElement 表示終結點使用 SOAP 訊息安全性。每個繫結元素通常具有這樣的屬性:它們進一步描述與終結點通訊的方式 的細節。例如,ReliableSessionBindingElement 有一個 Assurances 屬性,它指定所需的郵件傳遞保證,如無,至少一次,至多一次,或正好一次。
圖 4. 一個具有三個繫結元素的綁定樣本
綁定中繫結元素的順序和類型十分重要:繫結元素的集合用於構建根據其中繫結元素的順序排序的通訊堆棧。最後一個添加到集合中的繫結元素對應於通訊堆棧的底部元素,而第一個繫結元素對應於頂部元素。傳入訊息自下向上流經堆棧,而傳出訊息自上向下流經堆棧。因此,集合中繫結元素的順序直接影響通訊堆棧組件處理訊息的順序。請注意,WCF 提供一組預定義的綁定,在大多數方案中可以使用這些綁定而不用定義自訂綁定。
約定
WCF 約定是一個操作的集合,這些操作指定終結點與外界通訊的內容。每個操作都是一個簡單的訊息交換,例如單向或請求/應答訊息交換。
ContractDescription 類用於描述 WCF 約定及其操作。在 ContractDescription 中,每個 Contract 操作都有一個對應的 OperationDescription,它們描述操作的各個方面,如操作是單向還是請求/應答。每個 OperationDescription 還使用一個 MessageDescriptions 集合描述組成操作的各個訊息。
利用 WCF 編程模型,ContractDescription 通常從定義約定的介面或類進行建立。該類型使用 ServiceContractAttribute 進行注釋,其對應於終結點操作的方法使用OperationContractAttribute 進行注釋。您也可以手動構建一個 ContractDescription,無需從使用屬性注釋的 CLR 類型開始。
一個雙工 約定定義兩組邏輯操作:一組操作是,服務向用戶端公開以進行調用;另一組操作是,用戶端向服務公開以進行調用。用於定義雙工約定的程式模型會將每組操作分為一個單獨的類型(每種類型必須是一個類或一個介面),並使用 ServiceContractAttribute 注釋表示服務作業的約定,引用定義用戶端(或回調)操作的約定。此外,ContractDescription 還包含對每種類型的引用,從而可以將其組成一個雙工約定。
與綁定類似,每個約定都有一個在服務中繼資料中唯一標識該約定的名稱和命名空間。
每個約定還有一個 ContractBehaviors 集合,它是修改或擴充約定行為的模組。下一部分對這些行為進行更詳細的說明。
圖 5. ContractDescription 類描述 WCF 約定
行為
行為是修改或擴充服務或用戶端功能的類型。例如,ServiceMetadataBehavior 實現的中繼資料行為控制服務是否發布中繼資料。同樣,安全行為控制類比和授權,而事務行為控制登記和自動完成事務。
行為還參與構建通道的過程,它可以根據使用者指定的設定和/或服務或通道的其他方面修改該通道。
服務行為是實現 IServiceBehavior 並將其應用於服務的類型。同樣,通道行為是實現 IChannelBehavior 並將其應用於用戶端通道的類型。
服務和通道描述
ServiceDescription 類是一個記憶體內結構,它描述一個 WCF 服務,包括服務公開的終結點、應用於服務的行為,以及實現該服務的類型(一個類)(參見圖 6)。ServiceDescription 用於建立中繼資料、代碼/配置和通道。
您可以手動構建該 ServiceDescription 對象。您也可以從使用特定 WCF 屬性注釋的類型建立它,這是較為常見的情況。該類型的代碼可以手動編寫,也可以使用 WCF 工具(名為 svcutil.exe)從 WSDL 文檔產生。
儘管 ServiceDescription 對象可以顯式建立並填充,但它們通常作為運行服務的一部分在後台建立。
圖 6. ServiceDescription 物件模型
在用戶端同樣如此,ChannelDescription 描述一個到特定終結點的 WCF 用戶端通道(圖 7)。ChannelDescription 類有一個 IchannelBehaviors 的集合,IchannelBehaviors 是應用於通道的行為。它還有一個描述終結點(通道與該終結點進行通訊)的 ServiceEndpoint。
請注意,與 ServiceDescription 不同,ChannelDescription 只包含一個代表目標終結點(通道與該終結點進行通訊)的 ServiceEndpoint。
圖 7. ChannelDescription 物件模型
WCF 運行時
WCF 運行時是一組負責發送和接收訊息的對象。例如,格式化訊息、應用安全性、使用各種傳輸協議傳輸和接收訊息,以及向適當的操作分發接收到的訊息,所有這些操作都在 WCF 運行時中發生。以下部分闡釋 WCF 運行時的主要概念。
訊息
WCF 訊息是用戶端和終結點之間的資料交換單元。訊息本質上是 SOAP 訊息 InfoSet 的一個記憶體內表示形式。請注意,訊息不與文本 XML 綁定在一起。另外,根據所使用的編碼機制,訊息可以使用 WCF 二進位格式、文本 XML 或任何其他自訂格式序列化。
通道
通道是將訊息發送至終結點和從終結點接收訊息的核心抽象。從廣義上講,有兩類通道:傳輸通道使用某種形式的傳輸協議(如 TCP、UDP 或 MSMQ)處理髮送或接收不透明的八位位元組流。另一方面,協議通道通過處理並有可能修改訊息實現基於 SOAP 的協議。例如,安全通道添加並處理 SOAP 訊息頭,並且可能通過對其進行加密修改訊息體。通道是可編輯的,因此一層通道可以位於另一層通道之上,而另一層通道又可以位於第三層通道之上。
EndpointListener
EndpointListener 是與 ServiceEndpoint 等效的運行時。ServiceEndpoint 的 EndpointAddress、約定和綁定(代表位置、內容 和方式)分別對應於 EndpointListener 的偵聽地址、訊息篩選和分發,以及通道堆棧。EndpointListener 包含負責發送和接收訊息的通道堆棧。
ServiceHost 和 ChannelFactory
WCF 服務運行時通常通過調用 ServiceHost.Open 在後台建立。ServiceHost(如圖 6 所示)驅動從服務類型建立 ServiceDescription,並使用配置和/或代碼中定義的終結點填充 ServiceDescription 的 ServiceEndpoint 集合。然後,ServiceHost 使用 ServiceDescription 為 ServiceDescription 中的每個 ServiceEndpoint 以 EndpointListener 對象的形式建立一個通道堆棧。
圖 8. ServiceHost 物件模型
同樣,在用戶端,用戶端運行時由 ChannelFactory 建立,後者等效於用戶端的 ServiceHost。
ChannelFactory 驅動根據約定的類型、綁定以及 EndpointAddress 建立一個 ChannelDescription。然後,它使用該 ChannelDescription 用戶端的通道堆棧。
與服務運行時不同,用戶端運行時不包括含 EndpointListener,因為用戶端始終啟動到服務的串連,這樣就無需"偵聽"傳入的串連。
返回頁首
程式碼範例
本部分提供的程式碼範例說明如何構建服務和用戶端。這些樣本旨在使上述概念更加具體化,而不是教您 WCF 編程。
定義並實現約定
如前所述,定義約定最簡單的方法是建立一個介面或類,並使用 ServiceContractAttribute 對其加以注釋,使系統能夠通過它輕鬆地建立一個 ContractDescription。
使用介面或類定義約定時,作為約定成員的每個介面或類方法都必須使用 OperationContractAttribute 進行注釋。例如:
using System.ServiceModel;//a WCF contract defined using an interface[ServiceContract]public interface IMath{ [OperationContract] int Add(int x, int y);}
在本例中,實現約定僅僅是建立一個實現 IMath 的類。該類成為 WCF 服務類。例如:
//the service class implements the interfacepublic class MathService : IMath{ public int Add(int x, int y) { return x + y; }}
定義終結點並啟動服務
終結點可在代碼或配置中進行定義。在下面的樣本中,DefineEndpointImperatively 方法顯示在代碼中定義終結點並啟動服務的最簡單方法。
DefineEndpointInConfig 方法顯示在配置中定義的等效終結點(配置樣本在以下代碼之後)。
public class WCFServiceApp{ public void DefineEndpointImperatively() { //create a service host for MathService ServiceHost sh = new ServiceHost(typeof(MathService)); //use the AddEndpoint helper method to //create the ServiceEndpoint and add it //to the ServiceDescription sh.AddServiceEndpoint( typeof(IMath), //contract type new WSHttpBinding(), //one of the built-in bindings "http://localhost/MathService/Ep1"); //the endpoint‘s address //create and open the service runtime sh.Open(); } public void DefineEndpointInConfig() { //create a service host for MathService ServiceHost sh = new ServiceHost (typeof(MathService)); //create and open the service runtime sh.Open(); }}<!-- configuration file used by above code --><configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.serviceModel> <services> <!-- service element references the service type --> <service type="MathService"> <!-- endpoint element defines the ABC‘s of the endpoint --> <endpoint address="http://localhost/MathService/Ep1" binding="wsHttpBinding" contract="IMath"/> </service> </services> </system.serviceModel></configuration>
向終結點發送訊息
以下代碼顯示向 IMath 終結點發送訊息的兩種方法。SendMessageToEndpoint 隱藏通道的建立,這在後台發生,而 SendMessageToEndpointUsingChannel 樣本顯式進行通道的建立。
SendMessageToEndpoint 中的第一個樣本使用一個名為 svcutil.exe 的工具以及服務的中繼資料來產生一個約定(本樣本中的 IMath)、一個實現該約定的代理類(本樣本中的 MathProxy),以及相關聯的配置(此處未顯示)。再次強調,IMath 定義的約定指定了內容(即可以執行的操作),而產生的配置包含一個綁定(方式)和一個地址(位置)。
使用該代理類只需對其進行執行個體化並調用 Add 方法。在後台,該代理類將建立一個通道,並使用該通道與終結點通訊。
下面的 SendMessageToEndpointsUsingChannel 中的第二個樣本顯示如何使用 ChannelFactory 與終結點直接通訊。在該樣本中,使用 ChannelFactory.CreateChannel 直接建立通道,而不是用代理類或配置。而且,ChannelFactory 建構函式採用這兩部分資訊作為參數,而不是使用配置來定義終結點的地址和綁定。定義一個終結點所需的第三部分資訊(即約定)作為類型 T 傳入。
using System.ServiceModel;//this contract is generated by svcutil.exe//from the service‘s metadatapublic interface IMath{ [OperationContract] public int Add(int x, int y) { return x + y; }}//this class is generated by svcutil.exe//from the service‘s metadata//generated config is not shown herepublic class MathProxy : IMath{ ...}public class WCFClientApp{ public void SendMessageToEndpoint() { //this uses a proxy class that was //created by svcutil.exe from the service‘s metadata MathProxy proxy = new MathProxy(); int result = proxy.Add(35, 7); } public void SendMessageToEndpointUsingChannel() { //this uses ChannelFactory to create the channel //you must specify the address, the binding and //the contract type (IMath) ChannelFactory factory=new ChannelFactory( new WSHttpBinding(), new EndpointAddress("http://localhost/MathService/Ep1")); IMath channel=factory.CreateChannel(); int result=channel.Add(35,7); factory.Close(); }}
定義自訂行為
定義自訂行為只需實現 IServiceBehavior(或用戶端行為的 IChannelBehavior)。以下代碼顯示一個實現 IServiceBehavior 的樣本行為。在 IServiceBehavior.ApplyBehavior 中,代碼檢查 ServiceDescription 並寫出每個 ServiceEndpoint 的地址、綁定和約定,以及 ServiceDescription 中每個行為的名稱。
這個特殊的行為也是一個屬性(從 System.Attribute 繼承),使其可以以聲明方式應用,如下所示。然而,行為不必成為屬性。
[AttributeUsageAttribute( AttributeTargets.Class, AllowMultiple=false, Inherited=false)]public class InspectorBehavior : System.Attribute, System.ServiceModel.IServiceBehavior{ public void ApplyBehavior( ServiceDescription description, Collection behaviors) { Console.WriteLine("-------- Endpoints ---------"); foreach (ServiceEndpoint endpoint in description.Endpoints) { Console.WriteLine("--> Endpoint"); Console.WriteLine("Endpoint Address: {0}", endpoint.Address); Console.WriteLine("Endpoint Binding: {0}", endpoint.Binding.GetType().Name); Console.WriteLine("Endpoint Contract: {0}", endpoint.Contract.ContractType.Name); Console.WriteLine(); } Console.WriteLine("-------- Service Behaviors --------"); foreach (IServiceBehavior behavior in description.Behaviors) { Console.WriteLine("--> Behavior"); Console.WriteLine("Behavior: {0}", behavior.GetType().Name); Console.WriteLine(); } }}
應用自訂行為
通過向 ServiceDescription(或用戶端上的 ChannelDescription)添加行為的執行個體,所有行為都可以以命令方式應用。例如,要以命令方式應用 InspectorBehavior,您可以編寫以下代碼:
ServiceHost sh = new ServiceHost(typeof(MathService));sh.AddServiceEndpoint( typeof(IMath), new WSHttpBinding(), "http://localhost/MathService/Ep1"); //Add the behavior imperativelyInspectorBehavior behavior = new InspectorBehavior();sh.Description.Behaviors.Add(behavior);sh.Open();
此外,從 System.Attribute 繼承的行為還能夠以聲明方式應用於服務。例如,因為 InspectorBehavior 繼承自 System.Attribute,所以它可以以聲明方式得以應用,如下所示:
[InspectorBehavior]public class MathService : IMath{ public int Add(int x, int y) { return x + y; }} 返回頁首
小結
WCF 服務公開了一個終結點集合,其中每個終結點都是與外界通訊的入口。每個終結點都有一個地址、一個綁定和一個約定 (ABC)。地址是終結點駐留的位置,綁定是終結點通訊的方式,約定是終結點通訊的內容。
在服務端,ServiceDescription 儲存 ServiceEndpoint 的集合,其中每個 ServiceEndpoint 都描述服務公開的一個終結點。根據該描述,ServiceHost 建立一個運行時,它針對 ServiceDescription 中的每個 ServiceEndpoint 包含了一個 EndpointListener。終結點的地址、綁定和約定(代表位置、內容 和方式)分別對應於 EndpointListener 的偵聽地址、訊息篩選和分發,以及通道堆棧。
同樣,在用戶端,ChannelDescription 儲存與用戶端通訊的一個 ServiceEndpoint。根據該 ChannelDescription,ChannelFactory 建立可以與服務的終結點通訊的通道堆棧。
概覽 Windows Communication Foundation (WCF) 體繫結構及其主要概念。程式碼範例示範 WCF 約定、終結點和行為