Windows Communication Foundation 體系結構概述
發(fā)布日期: 2006-5-15 | 更新日期: 2006-5-15
摘要:概覽 Windows Communication Foundation (WCF) 體系結構及其主要概念。代碼示例演示 WCF 約定、終結點(diǎn)和行為。
本頁(yè)內容
簡(jiǎn)介WCF 基礎代碼示例小結簡(jiǎn)介
本文檔提供 Windows Communication Foundation (WCF) 體系結構的概覽。本文旨在闡釋 WCF 中的主要概念以及它們如何協(xié)調工作。還有幾個(gè)代碼示例對這些概念進(jìn)行深入闡釋?zhuān)a不是本文檔的重點(diǎn)。
本文檔下面的部分分為以下兩個(gè)主要內容:
•
WCF 基礎:涵蓋 WCF 中的主要概念、術(shù)語(yǔ)和體系結構組件。
•
代碼示例:提供幾個(gè)較短的代碼示例,旨在闡釋并具體化"WCF 基礎"中涵蓋的概念。
返回頁(yè)首WCF 基礎
WCF 服務(wù)是一個(gè)公開(kāi)終結點(diǎn) 集合的程序。每個(gè)終結點(diǎn)都是一個(gè)與外界通訊的入口。
客戶(hù)端是一個(gè)與一個(gè)或多個(gè)終結點(diǎn)交換消息的程序??蛻?hù)端還可以公開(kāi)一個(gè)終結點(diǎn),從而以雙工消息交換的模式從服務(wù)接收消息。
以下部分更詳細地描述了這些基礎。
終結點(diǎn)
一個(gè)服務(wù)終結點(diǎn)具有一個(gè)地址、一個(gè)綁定 和一個(gè)約定。
終結點(diǎn)的地址是終結點(diǎn)駐留的網(wǎng)絡(luò )地址。EndpointAddress 類(lèi)表示一個(gè) WCF 終結點(diǎn)地址。
終結點(diǎn)的綁定指定終結點(diǎn)與外界通訊的方式,包括傳輸協(xié)議(例如,TCP、HTTP)、編碼(例如,文本、二進(jìn)制文件)以及安全要求(例如,SSL、SOAP 消息安全)等。Binding 類(lèi)表示 WCF 綁定。
終結點(diǎn)的約定指定終結點(diǎn)通訊的內容,它本質(zhì)上是操作中有組織的消息集合,這些操作具有基本的消息交換模式 (MEPs),如單工、雙工,以及請求/應答。ContractDescription 類(lèi)表示 WCF 約定。
ServiceEndpoint 類(lèi)表示終結點(diǎn),它具有一個(gè) EndpointAddress、一個(gè)綁定以及一個(gè) ContractDescription,分別對應于終結點(diǎn)的地址、綁定和約定(參見(jiàn)圖 1)。
圖 1. 每個(gè)服務(wù)的終結點(diǎn)包含一個(gè) EndpointAddress、一個(gè)綁定以及一個(gè)由 ContractDescription 表示的約定。
EndpointAddress
EndpointAddress 實(shí)際上是一個(gè) URI、一個(gè)標識和一個(gè)可選標頭的集合,如圖 2 所示。
終結點(diǎn)的安全標識通常就是它的 URI;然而在高級方案中,可以使用 Identity 地址屬性獨立于 URI 來(lái)顯式設置標識。
可選標頭用于提供除終結點(diǎn) URI 外的其他尋址信息。例如,地址標頭對于區分共享相同地址 URI 的多個(gè)終結點(diǎn)很有用。
圖 2. EndpointAddress 包含一個(gè) URI,AddressProperties 包含一個(gè)標識和一個(gè) AddressHeaders 集合。
綁定
綁定具有名稱(chēng)、命名空間,以及一個(gè)可編寫(xiě)的綁定元素的集合(圖 3)。綁定的名稱(chēng)和命名空間在服務(wù)的元數據中唯一標識該綁定。每個(gè)綁定元素都描述終結點(diǎn)與外界通訊的方式 的一個(gè)方面。
圖 3. 綁定類(lèi)及其成員
例如,圖 4 顯示一個(gè)包含三個(gè)綁定元素的綁定元素集合。每個(gè)綁定元素的存在都描述與終結點(diǎn)通訊的方式 的一部分。TcpTransportBindingElement 表示終結點(diǎn)將使用 TCP 作為傳輸協(xié)議與外界通訊。ReliableSessionBindingElement 表示終結點(diǎn)使用可靠的消息處理來(lái)提供消息傳遞保證。SecurityBindingElement 表示終結點(diǎn)使用 SOAP 消息安全性。每個(gè)綁定元素通常具有這樣的屬性:它們進(jìn)一步描述與終結點(diǎn)通訊的方式 的細節。例如,ReliableSessionBindingElement 有一個(gè) Assurances 屬性,它指定所需的郵件傳遞保證,如無(wú),至少一次,至多一次,或正好一次。
圖 4. 一個(gè)具有三個(gè)綁定元素的綁定示例
綁定中綁定元素的順序和類(lèi)型十分重要:綁定元素的集合用于構建根據其中綁定元素的順序排序的通訊堆棧。最后一個(gè)添加到集合中的綁定元素對應于通訊堆棧的底部元素,而第一個(gè)綁定元素對應于頂部元素。傳入消息自下向上流經(jīng)堆棧,而傳出消息自上向下流經(jīng)堆棧。因此,集合中綁定元素的順序直接影響通訊堆棧組件處理消息的順序。請注意,WCF 提供一組預定義的綁定,在大多數方案中可以使用這些綁定而不用定義自定義綁定。
約定
WCF 約定是一個(gè)操作的集合,這些操作指定終結點(diǎn)與外界通訊的內容。每個(gè)操作都是一個(gè)簡(jiǎn)單的消息交換,例如單向或請求/應答消息交換。
ContractDescription 類(lèi)用于描述 WCF 約定及其操作。在 ContractDescription 中,每個(gè) Contract 操作都有一個(gè)對應的 OperationDescription,它們描述操作的各個(gè)方面,如操作是單向還是請求/應答。每個(gè) OperationDescription 還使用一個(gè) MessageDescriptions 集合描述組成操作的各個(gè)消息。
利用 WCF 編程模型,ContractDescription 通常從定義約定的接口或類(lèi)進(jìn)行創(chuàng )建。該類(lèi)型使用 ServiceContractAttribute 進(jìn)行注釋?zhuān)鋵诮K結點(diǎn)操作的方法使用OperationContractAttribute 進(jìn)行注釋。您也可以手動(dòng)構建一個(gè) ContractDescription,無(wú)需從使用屬性注釋的 CLR 類(lèi)型開(kāi)始。
一個(gè)雙工 約定定義兩組邏輯操作:一組操作是,服務(wù)向客戶(hù)端公開(kāi)以進(jìn)行調用;另一組操作是,客戶(hù)端向服務(wù)公開(kāi)以進(jìn)行調用。用于定義雙工約定的程序模型會(huì )將每組操作分為一個(gè)單獨的類(lèi)型(每種類(lèi)型必須是一個(gè)類(lèi)或一個(gè)接口),并使用 ServiceContractAttribute 注釋表示服務(wù)操作的約定,引用定義客戶(hù)端(或回調)操作的約定。此外,ContractDescription 還包含對每種類(lèi)型的引用,從而可以將其組成一個(gè)雙工約定。
與綁定類(lèi)似,每個(gè)約定都有一個(gè)在服務(wù)元數據中唯一標識該約定的名稱(chēng)和命名空間。
每個(gè)約定還有一個(gè) ContractBehaviors 集合,它是修改或擴展約定行為的模塊。下一部分對這些行為進(jìn)行更詳細的說(shuō)明。
圖 5. ContractDescription 類(lèi)描述 WCF 約定
行為
行為是修改或擴展服務(wù)或客戶(hù)端功能的類(lèi)型。例如,ServiceMetadataBehavior 實(shí)現的元數據行為控制服務(wù)是否發(fā)布元數據。同樣,安全行為控制模擬和授權,而事務(wù)行為控制登記和自動(dòng)完成事務(wù)。
行為還參與構建信道的過(guò)程,它可以根據用戶(hù)指定的設置和/或服務(wù)或信道的其他方面修改該信道。
服務(wù)行為是實(shí)現 IServiceBehavior 并將其應用于服務(wù)的類(lèi)型。同樣,信道行為是實(shí)現 IChannelBehavior 并將其應用于客戶(hù)端信道的類(lèi)型。
服務(wù)和信道描述
ServiceDescription 類(lèi)是一個(gè)內存內結構,它描述一個(gè) WCF 服務(wù),包括服務(wù)公開(kāi)的終結點(diǎn)、應用于服務(wù)的行為,以及實(shí)現該服務(wù)的類(lèi)型(一個(gè)類(lèi))(參見(jiàn)圖 6)。ServiceDescription 用于創(chuàng )建元數據、代碼/配置和信道。
您可以手動(dòng)構建該 ServiceDescription 對象。您也可以從使用特定 WCF 屬性注釋的類(lèi)型創(chuàng )建它,這是較為常見(jiàn)的情況。該類(lèi)型的代碼可以手動(dòng)編寫(xiě),也可以使用 WCF 工具(名為 svcutil.exe)從 WSDL 文檔生成。
盡管 ServiceDescription 對象可以顯式創(chuàng )建并填充,但它們通常作為運行服務(wù)的一部分在后臺創(chuàng )建。
圖 6. ServiceDescription 對象模型
在客戶(hù)端同樣如此,ChannelDescription 描述一個(gè)到特定終結點(diǎn)的 WCF 客戶(hù)端信道(圖 7)。ChannelDescription 類(lèi)有一個(gè) IchannelBehaviors 的集合,IchannelBehaviors 是應用于信道的行為。它還有一個(gè)描述終結點(diǎn)(信道與該終結點(diǎn)進(jìn)行通訊)的 ServiceEndpoint。
請注意,與 ServiceDescription 不同,ChannelDescription 只包含一個(gè)代表目標終結點(diǎn)(信道與該終結點(diǎn)進(jìn)行通訊)的 ServiceEndpoint。
圖 7. ChannelDescription 對象模型
WCF 運行時(shí)
WCF 運行時(shí)是一組負責發(fā)送和接收消息的對象。例如,格式化消息、應用安全性、使用各種傳輸協(xié)議傳輸和接收消息,以及向適當的操作分發(fā)接收到的消息,所有這些操作都在 WCF 運行時(shí)中發(fā)生。以下部分闡釋 WCF 運行時(shí)的主要概念。
消息
WCF 消息是客戶(hù)端和終結點(diǎn)之間的數據交換單元。消息本質(zhì)上是 SOAP 消息 InfoSet 的一個(gè)內存內表示形式。請注意,消息不與文本 XML 綁定在一起。另外,根據所使用的編碼機制,消息可以使用 WCF 二進(jìn)制格式、文本 XML 或任何其他自定義格式序列化。
信道
信道是將消息發(fā)送至終結點(diǎn)和從終結點(diǎn)接收消息的核心抽象。從廣義上講,有兩類(lèi)信道:傳輸信道使用某種形式的傳輸協(xié)議(如 TCP、UDP 或 MSMQ)處理發(fā)送或接收不透明的八位字節流。另一方面,協(xié)議信道通過(guò)處理并有可能修改消息實(shí)現基于 SOAP 的協(xié)議。例如,安全信道添加并處理 SOAP 消息頭,并且可能通過(guò)對其進(jìn)行加密修改消息體。信道是可編輯的,因此一層信道可以位于另一層信道之上,而另一層信道又可以位于第三層信道之上。
EndpointListener
EndpointListener 是與 ServiceEndpoint 等效的運行時(shí)。ServiceEndpoint 的 EndpointAddress、約定和綁定(代表位置、內容 和方式)分別對應于 EndpointListener 的偵聽(tīng)地址、消息篩選和分發(fā),以及信道堆棧。EndpointListener 包含負責發(fā)送和接收消息的信道堆棧。
ServiceHost 和 ChannelFactory
WCF 服務(wù)運行時(shí)通常通過(guò)調用 ServiceHost.Open 在后臺創(chuàng )建。ServiceHost(如圖 6 所示)驅動(dòng)從服務(wù)類(lèi)型創(chuàng )建 ServiceDescription,并使用配置和/或代碼中定義的終結點(diǎn)填充 ServiceDescription 的 ServiceEndpoint 集合。然后,ServiceHost 使用 ServiceDescription 為 ServiceDescription 中的每個(gè) ServiceEndpoint 以 EndpointListener 對象的形式創(chuàng )建一個(gè)信道堆棧。
圖 8. ServiceHost 對象模型
同樣,在客戶(hù)端,客戶(hù)端運行時(shí)由 ChannelFactory 創(chuàng )建,后者等效于客戶(hù)端的 ServiceHost。
ChannelFactory 驅動(dòng)根據約定的類(lèi)型、綁定以及 EndpointAddress 創(chuàng )建一個(gè) ChannelDescription。然后,它使用該 ChannelDescription 客戶(hù)端的信道堆棧。
與服務(wù)運行時(shí)不同,客戶(hù)端運行時(shí)不包括含 EndpointListener,因為客戶(hù)端始終啟動(dòng)到服務(wù)的連接,這樣就無(wú)需"偵聽(tīng)"傳入的連接。
返回頁(yè)首代碼示例
本部分提供的代碼示例說(shuō)明如何構建服務(wù)和客戶(hù)端。這些示例旨在使上述概念更加具體化,而不是教您 WCF 編程。
定義并實(shí)現約定
如前所述,定義約定最簡(jiǎn)單的方法是創(chuàng )建一個(gè)接口或類(lèi),并使用 ServiceContractAttribute 對其加以注釋?zhuān)瓜到y能夠通過(guò)它輕松地創(chuàng )建一個(gè) ContractDescription。
使用接口或類(lèi)定義約定時(shí),作為約定成員的每個(gè)接口或類(lèi)方法都必須使用 OperationContractAttribute 進(jìn)行注釋。例如:
using System.ServiceModel;//a WCF contract defined using an interface[ServiceContract]public interface IMath{[OperationContract]int Add(int x, int y);}
在本例中,實(shí)現約定僅僅是創(chuàng )建一個(gè)實(shí)現 IMath 的類(lèi)。該類(lèi)成為 WCF 服務(wù)類(lèi)。例如:
//the service class implements the interfacepublic class MathService : IMath{public int Add(int x, int y){ return x + y; }}
定義終結點(diǎn)并啟動(dòng)服務(wù)
終結點(diǎn)可在代碼或配置中進(jìn)行定義。在下面的示例中,DefineEndpointImperatively 方法顯示在代碼中定義終結點(diǎn)并啟動(dòng)服務(wù)的最簡(jiǎn)單方法。
DefineEndpointInConfig 方法顯示在配置中定義的等效終結點(diǎn)(配置示例在以下代碼之后)。
public class WCFServiceApp{public void DefineEndpointImperatively(){//create a service host for MathServiceServiceHost sh = new ServiceHost(typeof(MathService));//use the AddEndpoint helper method to//create the ServiceEndpoint and add it//to the ServiceDescriptionsh.AddServiceEndpoint(typeof(IMath), //contract typenew WSHttpBinding(), //one of the built-in bindings"http://localhost/MathService/Ep1"); //the endpoint‘s address//create and open the service runtimesh.Open();}public void DefineEndpointInConfig(){//create a service host for MathServiceServiceHost sh = new ServiceHost (typeof(MathService));//create and open the service runtimesh.Open();}}<!-- configuration file used by above code --><configurationxmlns="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 --><endpointaddress="http://localhost/MathService/Ep1"binding="wsHttpBinding"contract="IMath"/></service></services></system.serviceModel></configuration>
向終結點(diǎn)發(fā)送消息
以下代碼顯示向 IMath 終結點(diǎn)發(fā)送消息的兩種方法。SendMessageToEndpoint 隱藏信道的創(chuàng )建,這在后臺發(fā)生,而 SendMessageToEndpointUsingChannel 示例顯式進(jìn)行信道的創(chuàng )建。
SendMessageToEndpoint 中的第一個(gè)示例使用一個(gè)名為 svcutil.exe 的工具以及服務(wù)的元數據來(lái)生成一個(gè)約定(本示例中的 IMath)、一個(gè)實(shí)現該約定的代理類(lèi)(本示例中的 MathProxy),以及相關(guān)聯(lián)的配置(此處未顯示)。再次強調,IMath 定義的約定指定了內容(即可以執行的操作),而生成的配置包含一個(gè)綁定(方式)和一個(gè)地址(位置)。
使用該代理類(lèi)只需對其進(jìn)行實(shí)例化并調用 Add 方法。在后臺,該代理類(lèi)將創(chuàng )建一個(gè)信道,并使用該信道與終結點(diǎn)通訊。
下面的 SendMessageToEndpointsUsingChannel 中的第二個(gè)示例顯示如何使用 ChannelFactory 與終結點(diǎn)直接通訊。在該示例中,使用 ChannelFactory.CreateChannel 直接創(chuàng )建信道,而不是用代理類(lèi)或配置。而且,ChannelFactory 構造函數采用這兩部分信息作為參數,而不是使用配置來(lái)定義終結點(diǎn)的地址和綁定。定義一個(gè)終結點(diǎn)所需的第三部分信息(即約定)作為類(lèi)型 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 metadataMathProxy 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();}}
定義自定義行為
定義自定義行為只需實(shí)現 IServiceBehavior(或客戶(hù)端行為的 IChannelBehavior)。以下代碼顯示一個(gè)實(shí)現 IServiceBehavior 的示例行為。在 IServiceBehavior.ApplyBehavior 中,代碼檢查 ServiceDescription 并寫(xiě)出每個(gè) ServiceEndpoint 的地址、綁定和約定,以及 ServiceDescription 中每個(gè)行為的名稱(chēng)。
這個(gè)特殊的行為也是一個(gè)屬性(從 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();}}}
應用自定義行為
通過(guò)向 ServiceDescription(或客戶(hù)端上的 ChannelDescription)添加行為的實(shí)例,所有行為都可以以命令方式應用。例如,要以命令方式應用 InspectorBehavior,您可以編寫(xiě)以下代碼:
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 繼承的行為還能夠以聲明方式應用于服務(wù)。例如,因為 InspectorBehavior 繼承自 System.Attribute,所以它可以以聲明方式得以應用,如下所示:
[InspectorBehavior]public class MathService : IMath{public int Add(int x, int y){ return x + y; }}
返回頁(yè)首小結
WCF 服務(wù)公開(kāi)了一個(gè)終結點(diǎn)集合,其中每個(gè)終結點(diǎn)都是與外界通訊的入口。每個(gè)終結點(diǎn)都有一個(gè)地址、一個(gè)綁定和一個(gè)約定 (ABC)。地址是終結點(diǎn)駐留的位置,綁定是終結點(diǎn)通訊的方式,約定是終結點(diǎn)通訊的內容。
在服務(wù)端,ServiceDescription 保存 ServiceEndpoint 的集合,其中每個(gè) ServiceEndpoint 都描述服務(wù)公開(kāi)的一個(gè)終結點(diǎn)。根據該描述,ServiceHost 創(chuàng )建一個(gè)運行時(shí),它針對 ServiceDescription 中的每個(gè) ServiceEndpoint 包含了一個(gè) EndpointListener。終結點(diǎn)的地址、綁定和約定(代表位置、內容 和方式)分別對應于 EndpointListener 的偵聽(tīng)地址、消息篩選和分發(fā),以及信道堆棧。
同樣,在客戶(hù)端,ChannelDescription 保存與客戶(hù)端通訊的一個(gè) ServiceEndpoint。根據該 ChannelDescription,ChannelFactory 創(chuàng )建可以與服務(wù)的終結點(diǎn)通訊的信道堆棧。
轉到原英文頁(yè)面返回頁(yè)首