WCF入门到精通(二)——契约
第一次接觸WCF,如有寫的不對的地方有望大家指出來,謝謝!!
本篇文章主要說下WCF中的契約的種類、契約的種類、如何定義契約等內(nèi)容。
?????? 契約是一種雙邊或多邊的協(xié)議,是利益相關方就某個問題達成的一種共識,契約確保了服務的正常調(diào)用,客戶端以契約的方式進行服務調(diào)用,而服務則需要照契約規(guī)定的方式提供服務。契約是服務提供的一組操作的描述,從功能上講每個操作對應著某個具體的功能實現(xiàn),以及調(diào)用這個操作的輸入和輸出;從消息交換層面上講,每個操作定義了所采用的消息交換模式和消息本身的結(jié)構(gòu)。
主要內(nèi)容:
??? 1.什么是契約?
??? 2.契約有幾種?他們都有什么用途
??? 3.如何定義契約?
??? 4.契約是獨立于平臺的么?
??? 5.契約和以往哪種技術(shù)比較想像,又有什么不同
一、什么是契約?
? 任何一個分布式應用程序,它之所以能夠互相傳遞消息,都是事先制定好數(shù)據(jù)交換規(guī)則的,這個規(guī)則正是交換數(shù)據(jù)的雙方(比如服務器端和客戶端)能彼此理解對方 的依據(jù),WCF作為分布式開發(fā)技術(shù)的一種,同樣具有這樣一種特性。而在WCF中制定的的規(guī)則就被稱之為契約(Contract),它是WCF的消息標準, 是任何一個wcf程序不可或缺的一部分。
二、契約的種類
?在WCF中,契約分為四種,它們分別為:
?? 1.服務契約
???? 服務契約描述了暴露給外部的類型(接口或類)、服務所支持的操作、使用的消息交換模式和消息的格式。每個WCF服務必須實現(xiàn)至少一個服務契約。使用服務契約必須要引用命名空間System.ServiceModel 。服務契約中常用到的三個特性:
? ServiceContractAttribute
?
??? 該特性定義在類或接口上,用來描述一個相關操作的集合。ServiceContractAttribute特性還有如下的一些屬性值可以設置:
?
??? Name:給服務契約定義一個名稱,而不是使用接口或是類的類型名,在客戶端添加服務引用時會用到。
?
??? Namespace:命名空間,默認值為http://tempuri.org。
?
??? CallbackContract:將另一個服務契約定義為回調(diào)契約,使得客戶端可以接收服務端的異步消息。
?
??? ProtectionLevel:控制契約中發(fā)送給消息的保護方式是否需要被簽名和加密。該屬性為?? System.Net.Security.ProtectionLevel枚舉類型。
?
???? SessionMode:確定會話是否為公開服務契約的端點所支持。
?
???? ConfigurationName:服務的配置名稱。
?
[ServiceContract(Name="HelloWorld",Namespace="http://oec2003.cnblogs.com"] public interface IHelloWorldService { }OperationContractAttribute
?? 用OperationContractAttribute標記的方法即為一個服務操作,簡單的使用該特性就可以讓一個方法加入到服務契約的操作隊列中,可以被客戶端所調(diào)用。該特性也有一些設置消息交換方式的屬性。如下
?? Name:定義一個操作名稱,而不是使用方法名稱。
?? Action:該操作消息的動作標題。
?? ReplyAction:響應該操作消息的動作標題。
?? IsOneWay:設置該操作是否單向和沒有回復,如果操作是單向的,將不支持ReplyAction。
?? ProtectionLevel:允許你控制特定的操作消息是否被保護,操作中的ProtectionLevel屬性將覆蓋服務契約中的ProtectionLevel。該屬性為System.Net.Security.ProtectionLevel枚舉類型。
?? IsInitiating:操作是否可以用來初始化會話。
?? IsTerminating:操作是否中止一個會話。
?? AsyncPattern:將服務操作定義為異步實現(xiàn)模式。
[ServiceContract(Namespace="http://oec2003.cnblogs.com",Name="oec2003",ConfigurationName="IHelloWorldService")] public interface IHelloWorldService {[OperationContract(Name="oec2003SayHello",Action = "http://oec2003.cnblogs.com/IHelloWorldService/Hello",ReplyAction = "http://oec2003.cnblogs.com/IHelloWorldService/HelloReply")]string SayHello(); }??? MessageParameterAttribute
?? 使用 MessageParameterAttribute 可以控制參數(shù)或返回值的名稱。此屬性對于已用 MessageContractAttribute 特性標記的參數(shù)無效。該特性只有一個Name屬性,看如下代碼:
[ServiceContract(Namespace="http://oec2003.cnblogs.com",Name="oec2003",ConfigurationName="IHelloWorldService")] public interface IHelloWorldService {[OperationContract][return: MessageParameter(Name = "responseString")]string SayHello([MessageParameter(Name = "string")]string meg); }?2.數(shù)據(jù)契約
?
使用數(shù)據(jù)契約必須引用System.Runtime.Serialization命名空間,在類型上使用DataContractAttribute可以創(chuàng)建數(shù)據(jù)契約,類型中的成員使用DataMember標記。代碼如下:
[DataContract] public class User {[DataMember]public int Age { get; set; }[DataMember]public string Name { get; set; }[DataMember]public string Email { get; set; } }DataContractAttribute
DataContractAttribute特性定義在類型之上,類型包括類、結(jié)構(gòu)、枚舉但不包括接口。 DataContractAttribute特性不能被繼承,即繼承自有DataContractAttribute特性標記的類并不是數(shù)據(jù)契約,必須顯 示使用DataContractAttribute標記才能成為數(shù)據(jù)契約。DataContractAttribute特性有IsReference、 Name和Namespace三個屬性:
IsReference:bool類型,表示在進行序列化的時候是否保持對象現(xiàn)有的引用結(jié)構(gòu)。
Name:名稱。
Namespace:命名空間。
[DataContract(IsReference=true,Name="MyUser",Namespace="http://oec2003.cnblogs.com")] public class User {[DataMember]public int Age { get; set; }[DataMember]public string Name { get; set; }[DataMember]public string Email { get; set; } }DataMemberAttribute
使用DataMemberAttribute標記的類型成員才能成為數(shù)據(jù)契約的數(shù)據(jù)成員。這個和服務契約中的OperationContractAttribute類似。DataMemberAttribute特性有如下四個屬性:
EmitDefaultValue:表明在數(shù)據(jù)成員的值等于默認值的情況下,是否還須要將其序列化到最終的XML中,默認值為true,表示默認值會參與序列化。
IsRequired:bool類型,表明屬性成員是否是必須的成員,默認值為false。
Name:數(shù)據(jù)成員的別名。
Order:相應的數(shù)據(jù)成員在最終序列化的XML中出現(xiàn)的位置,默認是按字母順序排列的。
[DataContract(IsReference=true,Name="MyUser",Namespace="http://oec2003.cnblogs.com")] public class User {[DataMember(EmitDefaultValue=true,IsRequired=true,Name="Oec2003_Age",Order=1)]public int Age { get; set; }[DataMember(EmitDefaultValue = true, IsRequired = true, Name = "Oec2003_Name", Order = 2)]public string Name { get; set; }[DataMember(EmitDefaultValue = true, IsRequired = false, Name = "Oec2003_Email", Order = 3)]public string Email { get; set; }3.消息契約
使用消息契約必須引用System.ServiceModel命名空間,消息契約和數(shù)據(jù)契約一樣都是定義在數(shù)據(jù)類型上。和數(shù)據(jù)契約不同的是消息契約 更多的是關注數(shù)據(jù)成員在SOAP消息中的表示。定義一個消息契約需要用到MessageContractAttribute特性,另外還涉及到 MessageHeaderAttribute和MessageBodyMemberAttribute這兩個特 性,MessageContractAttribute特性標記在類型上,MessageHeaderAttribute和 MessageBodyMemberAttribute特性標記在數(shù)據(jù)成員上。
[MessageContract] public class MessageTest {[MessageHeader]public int Age { get; set; }[MessageHeader]public string Name { get; set; }[MessageBodyMember]public string Email { get; set; } }MessageContractAttribute
通過在一個類型上使用MessageContractAttribute標記可以使之成為一個消息契約。MessageContractAttribute特性含有如下幾個屬性:
IsWrapped:是否為定義的主體成員(一個或者多個)添加一個額外的根節(jié)點。
WrapperName:根節(jié)點的名稱。
WrapperNamespace:根節(jié)點的命名空間。
ProtectionLevel:表示保護級別,WCF中通過System.Net.Security.ProtectionLevel枚舉定義消息的保護級別。一般有3種可選的保護級別:None、Sign和EncryptAndSign。
[MessageContract(IsWrapped=false,WrapperName="MyMessage",WrapperNamespace="http://oec2003.com")] public class MessageTest {//省略 }MessageHeaderAttribute
?
使用MessageHeaderAttribute標記的數(shù)據(jù)成員將會出現(xiàn)在SOAP消息的頭部,該特性包含下面幾個屬性:
Actor:為一個URI值,表示處理該報頭的目標節(jié)點。
MustUnderstand:bool類型,表明Actor定義的節(jié)點是否必須理解并處理該節(jié)點。
Name:名稱。
Namespace:命名空間。
ProtectionLevel:表示保護級別。
Relay:表明該報頭是否需要傳遞到下一個SOAP節(jié)點。
[MessageContract] public class MessageTest {[MessageHeader(Actor="http://oec2003.com/Age",MustUnderstand=true,Name="MyAge",Namespace="http://oec2003.com",Relay=true)]public int Age { get; set; }[MessageHeader]public string Name { get; set; } }MessageBodyMemberAttribute
使用MessageHeaderAttribute標記的數(shù)據(jù)成員將會出現(xiàn)在SOAP消息的主體部分,該特性包含下面的屬性:
Order:Order屬性用來控制成員在SOAP主體部分中出現(xiàn)的位置,默認按字母順序排列。
Name:名稱。
Namespace:命名空間。
ProtectionLevel:表示保護級別。
[MessageContract(IsWrapped=false,WrapperName="MyMessage",WrapperNamespace="http://oec2003.com")] public class MessageTest {[MessageBodyMember(Order = 1)]public string Email { get; set; } }二、如何定義契約?
可參考資料
http://www.cnblogs.com/artech/archive/2007/02/28/659331.html
http://www.rainsts.net/article.asp?id=427
http://www.rainsts.net/article.asp?id=429
http://www.rainsts.net/article.asp?id=430
?
?
?? 三、契約是獨立于平臺的么?
?
??? WCF作為一種能夠跨平臺的體系框架,其應用肯定會有異構(gòu),異網(wǎng)的情況發(fā)生,那么作為通訊依據(jù)的契約能否自動適用于上述情況呢?答案是肯定的,契約是獨立 于平臺之外的,它只約束通訊的雙方應該遵守什么樣的規(guī)則,而絲毫不管雙方各自采用的是什么樣的技術(shù)和什么樣的操作系統(tǒng),也只有這樣,WCF才能有真正的生 命力。
?
?
?
四、契約和以往哪種技術(shù)比較相像,又有什么不同?
????如果非要拿契約和以往的技術(shù)相比較 的話,契約和asp.net xml web service的聲明性編程模型甚是相似,比如在web service中在類上標記WebServiceAttribute便可以將此類用于遠程調(diào)用,而將方法添加WebMethondAttribute也可 以將其暴露給遠程客戶端,這和WCF中的ServiceContract和OperationContract簡直如出一轍,但不同的是,WCF中的契約 要比Xml Web Service中的要詳盡的多,比如ServiceContract和OperationContract可以直接使用在接口上面,而實現(xiàn)該接口的類就繼 承了這種契約聲明,自動擁有契約所規(guī)范的動作和行為,這就使得程序員更方便的使用面向接口的編程方式,可以使同一服務擁有不同的實現(xiàn),在新舊版本升級的同 時,能夠使新老版本共同運行。
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/xiaowuzi/p/3547341.html
總結(jié)
以上是生活随笔為你收集整理的WCF入门到精通(二)——契约的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MockMVC
- 下一篇: CAJ格式文件怎么转换成Word