WCF 筆記 – 簡(jiǎn)單使用:
WCF 概念:
WCF 是 “Windows Communication Foundation ”的縮寫(xiě),Windows Communication Foundation (WCF) 是一個(gè)運(yùn)行庫(kù)和一組 API,用于創(chuàng)建在服務(wù)與客戶端之間發(fā)送消息的系統(tǒng)。 它使用相同的基礎(chǔ)結(jié)構(gòu)和 API 來(lái)創(chuàng)建應(yīng)用程序,這些應(yīng)用程序可與同一計(jì)算機(jī)系統(tǒng)上或駐留在另一家公司內(nèi)并通過(guò) Internet 訪問(wèn)的系統(tǒng)上的其他應(yīng)用程序進(jìn)行通信。
WCF 通過(guò)一種面向服務(wù)的新型編程模型簡(jiǎn)化了關(guān)聯(lián)應(yīng)用程序的開(kāi)發(fā)。通過(guò)提供分層的體系結(jié)構(gòu),WCF 支持多種風(fēng)格的分布式應(yīng)用程序開(kāi)發(fā)。 WCF 通道體系結(jié)構(gòu)在底層提供了異步的非類型化消息傳遞基元。
WCF體系結(jié)構(gòu)圖:
Contract(契約) :
在WCF中所有需要向外部服務(wù)的方法或?qū)ο蠖夹枰獦?biāo)明契約屬性。
基本契約有4種:
服務(wù)契約(Service Contract) :
指示接口或類在 Windows Communication Foundation (WCF) 應(yīng)用程序中定義服務(wù)協(xié)定。
數(shù)據(jù)契約(Data Contract) :
指定該類型要定義或?qū)崿F(xiàn)一個(gè)數(shù)據(jù)協(xié)定,并可由序列化程序(如 System.Runtime.Serialization.DataContractSerializer)進(jìn)行序列化。若要使其類型可序列化,類型作者必須為其類型定義數(shù)據(jù)協(xié)定。
異常契約(Fault Contract):
指定服務(wù)操作遇到處理錯(cuò)誤時(shí)返回的一個(gè)或多個(gè) SOAP 錯(cuò)誤
消息契約(Message Contract):
定義與 SOAP 消息相對(duì)應(yīng)的強(qiáng)類型類。
簡(jiǎn)單WCFService創(chuàng)建:
WCF服務(wù)端:
這里創(chuàng)建一個(gè)最簡(jiǎn)單,以Web形式發(fā)布的WCFService,現(xiàn)在這里創(chuàng)建一個(gè)“WCF 服務(wù)應(yīng)用程序”名為 “WebWcfServiceA”。
項(xiàng)目需要 System.ServiceModel 與 System.Runtime.Serialization 的引用?;旧纤杏嘘P(guān)于WCF的項(xiàng)目,都會(huì)需要到引用這兩個(gè)組件。
此項(xiàng)目中有一個(gè)接口 IWebWcfServiceA 用于表示WCF公開(kāi)的方法。
[ServiceContract]
public interface IWebWcfServiceA
{
[OperationContract]
string serviceFunction(int value);
}
這里接口中的契約屬性ServiceContract 用于標(biāo)明這個(gè)接口是公開(kāi)可調(diào)用的。
方法中的契約屬性 OperationContract 用于標(biāo)明這個(gè)方法是公開(kāi)可調(diào)用的。
除了接口外,還需要一個(gè)WCF服務(wù)文件 ,在這里命名為“WebWcfServiceA.svc”。
public class WebWcfServiceA : IWebWcfServiceA
{
public string serviceFunction(int value)
{
return string.Format("You entered: {0}", value);
}
}
這個(gè)類是WCF的主體,它繼承于WCF公開(kāi)的接口并完成接口的功能。
這里需要注意的是,所有對(duì)接口ServiceContract 和服務(wù)文件 WebWcfServiceA.svc進(jìn)行過(guò)名稱更改的,都需要在配置文件中進(jìn)行相應(yīng)的更改。
在配置文件中的 <system.serviceModel>節(jié)里面說(shuō)明了WCF相關(guān)的配置,在這里需要注意的是元素service 和 endpoint 。 service 的 name 屬性指名了WCF 服務(wù)類的位置;endpoint 的contract 屬性指名了契約接口的位置。
客戶端:
現(xiàn)在為這個(gè)簡(jiǎn)單的WCFService創(chuàng)建一個(gè)簡(jiǎn)單的客戶端,控制臺(tái)程序“WebWcfAClient”。
最簡(jiǎn)單創(chuàng)建客戶端的辦法就是像創(chuàng)建Web Service那樣添加一個(gè)服務(wù)引用,這個(gè)服務(wù)引用直接指向剛才創(chuàng)建的WebWcfServiceA項(xiàng)目。
創(chuàng)建成功后,項(xiàng)目會(huì)添加一份app.config,此文件記錄了關(guān)于WCF服務(wù)的信息,其中這里需要注意一下的是client 中的 endpointaddress ,這里記錄了指向WCF 服務(wù)的路徑。
創(chuàng)建這樣一個(gè)服務(wù)引用后,便可以直接調(diào)用其中暴露出來(lái)的方法。
static void Main()
{
WebWcfServiceA.WebWcfServiceAClient ServiceA = new WebWcfAClient.WebWcfServiceA.WebWcfServiceAClient();
Console.WriteLine(ServiceA.serviceFunction(0));
Console.ReadKey();
ServiceA.Close();
}
這種客戶端方式的調(diào)用,基本和webService的調(diào)用相似。
第二種WcfService創(chuàng)建:
因?yàn)楣_(kāi)暴露的方法是在接口上,所以除了使用服務(wù)引用的辦法來(lái)創(chuàng)建客戶端引用外,還可以通過(guò)使用引用該接口的辦法來(lái)調(diào)用WCF的服務(wù)。
契約接口:
首先,創(chuàng)建一個(gè)接口項(xiàng)目(IWebWcfServiceB)用于服務(wù)端和客戶端雙方的調(diào)用:
[ServiceContract]
public interface IService
{
[OperationContract]
CompositeType serviceFunction(int value);
}
[DataContract]
public class CompositeType
{
[DataMember]
public string strValue
{
get;
set;
}
}
這里的CompositeType類的屬性DataContract(數(shù)據(jù)契約)用于標(biāo)明此類是用在于WCF服務(wù)中提供數(shù)據(jù)的,并且此類是可以序列化的。
屬性strValue上的DataMember屬性標(biāo)明屬性strValue可以序列化。
服務(wù)端:
服務(wù)段只有一個(gè)文件WebWcfServiceB.svc ,
public class WebWcfServiceB : IService
{
public CompositeType serviceFunction(int value)
{
CompositeType ct = new CompositeType();
ct.strValue = string.Format("You entered: {0}", value);
return ct;
}
}
它基本和WebWcfServiceB.svc一致,只是繼承的接口被分離到另外一個(gè)項(xiàng)目中。
客戶端:
客戶端需要引用接口IWebWcfServiceB,還需要為接口創(chuàng)建一個(gè)代理類,用于調(diào)用WCF服務(wù)。
這個(gè)接口類可以手工創(chuàng)建,但是你運(yùn)行打開(kāi)上述的WebWcfServiceB.svc 文件時(shí)候會(huì)發(fā)現(xiàn)VS提供了一個(gè)工具svcutil.exe 來(lái)創(chuàng)建這個(gè)代理類。
這里是一個(gè)手工寫(xiě)的代理類:
public partial class ServiceClient : System.ServiceModel.ClientBase<IService>, IService
{
public ServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public CompositeType serviceFunction(int value)
{
return base.Channel.serviceFunction(value);
}
}
[DataContractAttribute]
public partial class CompositeType : object, System.Runtime.Serialization.IExtensibleDataObject
{
public System.Runtime.Serialization.ExtensionDataObject ExtensionData
{
get;
set;
}
[DataMemberAttribute]
public string strValue
{
get;
set;
}
}
需要注意的是這里的命名空間要和公開(kāi)接口的命名空間一致。
如果使用工具寫(xiě)出的代碼會(huì)有更多的實(shí)現(xiàn)方法,并且工具將會(huì)輸出一個(gè)名為output.config 的文件,此文件和使用服務(wù)引用時(shí)添加的配置文件一樣。
代理類的使用如下:
System.ServiceModel.WSHttpBinding binding = new System.ServiceModel.WSHttpBinding();
System.ServiceModel.EndpointAddress address =
new System.ServiceModel.EndpointAddress(new Uri("http://localhost/WebWcfServiceB.svc"));
ServiceClient ServiceB = new ServiceClient(binding, address);
CompositeType ct = ServiceB.serviceFunction(0);
Console.WriteLine(ct.strValue);
Console.ReadKey();
ServiceB.Close();
如果是使用配置文件的,可以直接ServiceClient ServiceB = new ServiceClient() 來(lái)讀取調(diào)用配置文件中的路徑。
WCF服務(wù)庫(kù):
除了使用上面兩種以WCF服務(wù)文件為主體,依附IIS的創(chuàng)建方式以外,還可以使用WCF服務(wù)庫(kù)來(lái)創(chuàng)建WCF服務(wù)。
直接創(chuàng)建一個(gè)WCF服務(wù)庫(kù),可以看見(jiàn)IDE為你創(chuàng)建了三份文件,一個(gè)公開(kāi)契約的接口,一個(gè)控制臺(tái)應(yīng)用程序的WCF服務(wù)主體,和一份配置文件。
這個(gè)結(jié)構(gòu)和之前創(chuàng)建WCF 服務(wù)應(yīng)用程序基本相同,只不過(guò)是主體由svc服務(wù)文件變?yōu)榱丝刂婆_(tái)的應(yīng)用程序。
服務(wù)端:
項(xiàng)目名稱:HostWcfServiceA。
[ServiceContract]
public interface IService
{
[OperationContract]
string serviceFunction(int value);
}
public class HostWcfServiceA : IService
{
public string serviceFunction(int value)
{
return string.Format("You entered: {0}", value);
}
}
此服務(wù)運(yùn)行后將會(huì)根據(jù)配置文件中baseAddress屬性的地址來(lái)監(jiān)聽(tīng),該地址只是用于通信,不能使用瀏覽器打開(kāi)。
客戶端:
創(chuàng)建一個(gè)新的控制臺(tái)程序HostWcfAClient 來(lái)作為客戶端,客戶端對(duì)此WCF服務(wù)的調(diào)用也可以使用服務(wù)引用,具體調(diào)用和WCF服務(wù)文件的方式一樣。
服務(wù)端除了使用配置文件來(lái)配置監(jiān)聽(tīng)路徑外,還可以使用代碼來(lái)配置監(jiān)聽(tīng)路徑,方法是使用另外一個(gè)應(yīng)用程序來(lái)作為服務(wù)主機(jī),讓客戶端調(diào)用。
服務(wù)端B:
此服務(wù)端B的服務(wù)庫(kù)與項(xiàng)目HostWcfServiceA 的服務(wù)庫(kù)一樣,添加多一個(gè)控制臺(tái)應(yīng)用程序作為服務(wù)器:
Uri baseAddress = new Uri("http://127.0.0.1:55555");
using (ServiceHost host = new ServiceHost(typeof(HostWcfServiceB.HostWcfServiceB), new Uri[] { baseAddress }))
{
BasicHttpBinding binding = new BasicHttpBinding();
host.AddServiceEndpoint(typeof(HostWcfServiceB.IService), binding, baseAddress);
host.Open();
Console.WriteLine("服務(wù)已啟動(dòng)");
Console.Read();
}
最后聲明: 此文只是本人學(xué)習(xí)WCF中的一點(diǎn)筆記,如有錯(cuò)謬,請(qǐng)指正。
本文源代碼下載
如對(duì)本文有疑問(wèn),請(qǐng)?zhí)峤坏浇涣髡搲?,廣大熱心網(wǎng)友會(huì)為你解答?。?點(diǎn)擊進(jìn)入論壇