WCF(Windows Communication Foundation,WCF)是基于Windows平台下開發和部署服務的軟體開發包(Software Development Kit,SDK)。WCF為服務提供了運作時環境(Runtime Environment),使得開發者能夠将CLR類型公開為服務,又能夠以CLR類型的方式使用服務。理論上講,建立服務并不一定需要WCF,但實際上,使用WCF卻可以使得建立服務的任務事半功倍。WCF是微軟對一系列産業标準定義的實作,包括服務互動、類型轉換、封送(Marshaling)以及各種協定的管理。正因為如此,WCF才能夠提供服務之間的互操作性。WCF還為開發者提供了大多數應用程式都需要的基礎功能子產品,提高了開發者的效率。WCF的第一個版本為服務開發提供了許多有用的功能,包括托管(Hosting)、服務執行個體管理(Service Instance Management)、異步調用、可靠性、事務管理、離線隊列調用(Disconnected Queued Call)以及安全性。同時,WCF還提供了設計優雅的可擴充模型,使開發人員能夠豐富它的基礎功能。事實上,WCF自身的實作正是利用了這樣一種可擴充模型。本書的其餘章節會專注于介紹這諸多方面的内容與特征。WCF的大部分功能都包含在一個單獨的程式集System.ServiceModel.dll中,命名空間為System.ServiceModel。
WCF的體系架構如下:

WCF的用戶端與服務端模型如下:
1 位址
WCF的每一個服務都有唯一的位址。位址包括服務位置和傳輸協定(傳輸樣式)。服務位置包括目标機器名、站點、網絡、端口、管道或隊列,以及一個可選的特定路徑或者URI。
位址常用格式為:[基位址]/[可選的URI],如“net.tcp://localhost:8081/MyService”,可以讀做“采用HTTP協定通路localhost機器,MyService服務在8081端口處等待使用者的調用”
基位址常用格式為:[傳輸協定]://[機器名或域名][:可選端口],如“net.tcp://localhost:8081”。
WCF支援多種傳輸樣式:
- HTTP 采用http、https協定進行傳輸,預設端口号80。
- TCP 采用net.tcp協定進行傳輸,預設位址為808。
- Peer network(對等網) 采用net.p2p進行傳輸,采用Windows的對等網傳輸機制。
- IPC(内部程序通信) 采用net.pipe進行傳輸,使用Windows的命名管道機制,隻能接收來自同一台機器的調用,且每台機器隻能打開一個命名管道。
- MSMQ 采用net.msmq進行傳輸,使用Windows的MSMQ機制,必須指定隊列名,如果是處理私有隊列,則必須指定隊列類型。
2 綁定
綁定将通信模式與互動方式直接的組合進行規範,将這些通信特征合理地組合在一起。一個綁定封裝了諸如傳輸協定、消息編碼、可靠性、安全性、事務傳播以及互操作性等相關選項的組合,使得它們保持一緻。
WCF定義了六種常用的綁定:
- 基本綁定 由BasicHttpBinding類提供,将WCF服務公開為Web服務。
- TCP綁定 由NetTcpBinding類提供,使用TCP協定通信,支援多種特性,包括可靠性、事務性、安全性及WCF之間通信的優化,缺點是用戶端必須使用WCF。
- IPC綁定 由NetNamedPipeBinding類提供,使用命名管道為同一機器的通信進行傳輸,支援的特性與TCP綁定類似,是性能和安全性最佳的綁定。
- Web服務綁定 由WSHttpBinding類提供,WS綁定使用HTTP或HTTPS進行傳輸,提供了諸如可靠性、事務性與安全性在内的多種特性,這些特性遵循WS-*标準,該綁定被設計用來與支援WS-*标準的系統進行互操作。
- WS雙向綁定 由WSDualHttpBinding類提供,支援雙向通信。
- MSMQ綁定 由NetMsmqBinding類提供,使用MSMQ進行傳輸。
3 契約
WCF的所有服務都公開為契約,契約與平台無關,是描述服務功能的标準方式。WCF包含4類契約:
- 服務契約 描述了用戶端能夠執行的服務操作。
- 資料契約 定義了與服務互動的資料類型。
- 錯誤契約 定義了服務抛出的錯誤,以及服務處理錯誤和傳遞錯誤到用戶端的方式。
- 消息契約 消息契約允許服務直接與消息互動,用于定制專有的消息格式,也意味着要自己的應用程式上下文,因為會增加代碼的複雜度,是以不屬于常見用法。
4 終結點
終結點是WCF進行通信的唯一手段,ChannelFactory<T>本質上是通過制定的終結點建立用于進行服務調用的服務代理。終結點在WCF體系中通過Systtm.ServiceModel.Description.ServiceEndpoint類型表示,其包含三個核心屬性——位址、綁定、契約。終結點是用來發送和接收消息的構造,終結點是真正意義上的接口,它包含了一個對象接口所需的全部資訊。每個服務至少必須公開一個業務終結點,每個終結點有且隻能擁有一個契約。服務上的所有終結點都包含了唯一的位址,而一個單獨的服務則可以公開多個終結點。這些結點可以使用相同或不同的綁定,公開相同或不同的契約。
5 中繼資料
服務的中繼資料描述服務的特征,外部實體需要了解這些特征以便與該服務進行通信。服務的中繼資料包括XML、架構文檔(用于定義服務的資料協定)和WSDL文檔(用于描述服務的方法)。啟用中繼資料後,WCF通過檢查服務及其終結點自動生成服務的中繼資料。
6 上下文
WCF上下文将服務宿主與公開本地CLR類型為服務的上下文組合在一起,上下文是服務執行個體最核心的執行範圍,上下文可以為空,即不包含任何服務執行個體。
7 宿主
WCF服務類不能憑空存在,每個WCF服務類必須托管在某個宿主程序中。單個宿主程序可以托管多個服務,而相同的服務類型也可以托管在多個宿主程序中,如果服務與用戶端駐留在相同的程序中,則稱為程序内托管。常用宿主如下:
- Web站點
- Windows窗體應用程式
- Windows服務
- Windows激活服務(WAS)
WCF宿主體系結構如下:
每個.NET宿主程序都包含了多個應用程式域,每個應用程式域包含零到多個宿主執行個體,每個服務宿主執行個體專門對于于一個特殊的服務類型。是以,建立一個宿主執行個體,實際上就是為對應于基位址的主控端器的類型注冊一個包含了所有終結點的服務宿主執行個體。每個服務宿主執行個體擁有零到多個上下文。一個上下文可以與零個或一個服務執行個體關聯。
8 代理
WCF不允許用戶端直接與服務互動,用戶端使用代理将調用轉發給服務。即使對象是本地的,WCF仍然使用遠端程式設計模型的執行個體化方式,并且使用代理。
示例
通過上面的介紹,我們從契約,服務,宿主,用戶端這四個步驟完成一個簡單的Demo,項目結構如下:
定義契約,也就是一個接口,這是這個接口有ServiceContract的标記,被暴露的方法被标記為OperationContract,資料的話被标記為DataContract
namespace WCFService
{
// 注意: 使用“重構”菜單上的“重命名”指令,可以同時更改代碼和配置檔案中的接口名“IService1”。
[ServiceContract]
public interface IWCFService
{
[OperationContract]
string GetData(int value);
[OperationContract]
string Greeting(string sName);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
// TODO: 在此添加您的服務操作
}
// 使用下面示例中說明的資料約定将複合類型添加到服務操作。
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
}
實作上面的接口
namespace WCFService
{
// 注意: 使用“重構”菜單上的“重命名”指令,可以同時更改代碼、svc 和配置檔案中的類名“Service1”。
public class WCFService : IWCFService
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
public string Greeting(string sName)
{
return "Hello ," + sName;
}
}
}
通過綁定實作服務的宿主,也就是A+B+C
namespace WCFHost
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(WCFService.WCFService)))
{
host.AddServiceEndpoint(typeof(WCFService.IWCFService), new BasicHttpBinding(),
new Uri("http://localhost:10000/Service/WCFService"));
if (host.State != CommunicationState.Opening)
host.Open();
Console.WriteLine("服務已經啟動!");
Console.ReadLine();
}
}
}
}
在用戶端需要添加,服務契約的引用。
namespace WCFClient
{
class Program
{
static void Main(string[] args)
{
EndpointAddress ea =
new EndpointAddress("http://localhost:10000/Service/WCFService");
IWCFService proxy =
ChannelFactory<IWCFService>.CreateChannel(new BasicHttpBinding(), ea);
Console.WriteLine(proxy.Greeting("劉宇"));
Console.ReadLine();
}
}
}
執行結果
有沒有看到和NETRemoting的寫法有點類似呢?