熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

WCF中的Data Contract:Data Contract概覽

2022-06-13   來源: .NET編程 

  在我們看來Service Orientation提供了一種對業務功能進行分解的方式針對SO我們把一個具體的業務流程或者一個復雜的功能分解成一個個獨立完成某項任務的子單元這些子單元通過一個個Service來承載對於Service本身來講他們應該是自治的獨自完成自己的功能不依賴於其他的Service但是Service的價值體現在它被潛在的消費者使用的程度這實際上包含兩方面的內容作為Service本身它如何將自己暴露出來供一切可能的潛在用戶調用這些潛在用戶不僅僅指那些不同的Client也包含其他的ServiceService Orientation其中一個特征就是Service should be composite鼓勵將一個個相關細粒度的Service組合成一個大的Service這樣有利於較大限度的實現重用而重用往往意味著更小的投入更佳的可維護性而另一方面就是這些消費者通過怎樣的方式來調用它所需要的Service

  這實際上體現了兩者相互交互的問題在一個分布式的環境中要實現兩者的交互有兩個必須要解決的問題如何保證Service的使用者對Service的調用能夠被Service端理解以及對Service的調用如何抵達Service Side後者實質上是關於communication的問題我們現在不去談它第一個問題就是Contract需要解決的問題

  我們知道SOA一個主要的目標就是促進不同技術平台的互操作要真正實現這樣一個宏偉的目標是一件極不容易的事情需要不同的廠商和標准組織相互協作制定一個大家一致遵循的標准這樣一個標准就是WS* 我們很清楚無論個個廠商各自的標准怎樣千差萬別但是有個標准是他們必須要遵循的那就是Internet的標准如果哪家公司拒絕Internet那肯定要被淘汰的而對於Internet基於Http的網絡協議和基於XML的數據表達已經成為了事實上的標准對於SOA來說XML不僅僅用於表示Service調用攜帶的數據(參數和返回值)更用於表示這個調用本身以及滿足各種要求的控制信息 比如基於SecuritySessionReliable MessagingTransaction等等的控制信息WS*就是一個基於XML的標准而對於SOA中的Contract所要做的就是尋求一種廠商中立的方式來表示Service的接口和用於交互的數據結構前者就是Service Contract後者就是Data Contract

  SOA中的一個Service由一組相關的Operation來構成Service Contract用於表示構成該Service所有Operation的Interface(而不是Implementation)說得更加具體點大家都知道Consumer和Service之間的交互都是通過Message的形式來實現的一次交互就是一次Message Exchange在不同的場景我們以不通過Pattern來進程Message Exchange比如我們通常使用RequestResponse的方式來向Service發送Request進而得到返回結果我們也可以以RequestForget的形式來異步地調用Service(不需要從Service獲取Response)我們可以讓一個Service在沒有收到任何Request的情況下以廣播的形式向注冊的Client發送通知當然我們還有其他不同的消息交互的模式我們把這些不同的信息交互方式稱為MEP(Message Exchange Pattern)也就是說一個Operation最終通過被最終轉換成了按照某種MEP進行的消息交互而Service Contract旨在實現對這種MEP的描述比如是否需要Request Message或者Response Message(如果僅僅有Response Message就是Notification的方式如果僅僅具有Request Message那就是我們上面談到的RequestForget的模式)和Message本身具有的格式

  上面我們說了Service Contract是以一種廠商中立的形式描述體現為某種模式的消極交互構成整個Service的所有Operation而我們也說了Consumer和Service的交互本質上看就是按照某種Pattern體現的一次Message Exchange好像具有了Service Contract的描述就可以了但是實際上單單有了Service Contract對Service的描述還不夠因為Service Contract本身缺乏對攜帶於Message用於信息傳遞的數據類型的描述而這是Data Contract需要解決的問題我們知道不同的技術平台對數據類型的表示是不一樣的可能某一種技術平台使用bit來表述一個浮點數另一種則使用bit所以要想實現不同技術平台的互操作將不同技術平台同一類型的數據以一種廠商中立的形式來描述是必須的

  概括的說SOA中的Service Contract和Data Contract就是一種廠商中立的數據呈現方式對Service Interface和Data Type的而Service的調用都是通過SOAP Message來實現SOAP是基於XML而對於XML結構的定義我們很自然地想到XSD我們可簡單地將SOA中的Contract看成是一個XSD

  Contract in WCF

  上面我們實際上是在一個廠商中立的前提下探討Contract這裡的Contract和具體的平台和技術無關接下來我們要談的是基於技術的話題討論一下WCF下的Contract簡單地說WCF中的Contract主要的功能就是如何將一個基於NET的CLR TypeInterface或者Class轉化成一個我們上面提到的Neutral Contract比如如果我們在一個Interface和它的成員上分別運用Service Contract Attribute和Operation Contract當我們Host實現了該Interface的Service的時候WCF就能將在一個NETspecific的CLR Type暴露成一個Neutral Service Contract同理對於一個我們通過在一個Class和它的成員上分別添加DataContractAttribute和DataMemberAttribute就可以就該CLR Type轉變成Neutral Data Contract

  比如我們一個運用了DataContractAttribute和DataMemberAttribute的Order class

  

  namespace ArtechDataContractVersioningService
{
[DataContract(Namespace=)]
public class Order
{
[DataMember(Order = )]
public Guid OrderID
{get;set;}

  [DataMember(Order = )]
public DateTime OrderDate
{ get; set; }

  [DataMember(Order = )]
public Guid SupplierID
{ get; set; }
}
}

  就可以轉變成另一種廠商中立的以XSD表示的Neutral Data Contract

  

  
xmlns:xs=

  xmlns:tns=
xmlns:ser=>
namespace="" />


[System.Runtime.Serialization.DataContractAttribute(Name="Order", Namespace="

  datacontractversioning")]
[System.SerializableAttribute()]
public partial class Order : object, System.Runtime.Serialization.IExtensibleDataObject,

  System.ComponentModel.INotifyPropertyChanged {

[System.NonSerializedAttribute()]
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

[System.Runtime.Serialization.OptionalFieldAttribute()]
private System.Guid OrderIDField;

[System.Runtime.Serialization.OptionalFieldAttribute()]
private System.DateTime OrderDateField;

[System.Runtime.Serialization.OptionalFieldAttribute()]
private System.Guid SupplierIDField;

[global::System.ComponentModel.BrowsableAttribute(false)]
public System.Runtime.Serialization.ExtensionDataObject ExtensionData {
get {
return this.extensionDataField;
}
set {
this.extensionDataField = value;
}
}

[System.Runtime.Serialization.DataMemberAttribute()]
public System.Guid OrderID {
get {
return this.OrderIDField;
}
set {
if ((this.OrderIDField.Equals(value) != true)) {
this.OrderIDField = value;
this.RaisePropertyChanged("OrderID");
}
}
}

[System.Runtime.Serialization.DataMemberAttribute(Order=1)]
public System.DateTime OrderDate {
get {
return this.OrderDateField;
}
set {
if ((this.OrderDateField.Equals(value) != true)) {
this.OrderDateField = value;
this.RaisePropertyChanged("OrderDate");
}
}
}

[System.Runtime.Serialization.DataMemberAttribute(Order=2)]
public System.Guid SupplierID {
get {
return this.SupplierIDField;
}
set {
if ((this.SupplierIDField.Equals(value) != true)) {
this.SupplierIDField = value;
this.RaisePropertyChanged("SupplierID");
}
}
}

public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

protected void RaisePropertyChanged(string propertyName) {
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.

  PropertyChanged;
if ((propertyChanged != null)) {
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(

  propertyName));
}
}
}

  通過上面這樣一個在Client自動生成的Order class,你就可以創建Order對象來調用相應的Service了。這種自動生成代碼的方式確實很省事,而且當Service端的Data Contract改變的時候,你只需要Update Service Reference就可以重新生成並覆蓋現有的代碼。但是,就我個人來說,我不要喜歡使用這樣的方式,如果對Service暴露出來的數據結構很熟悉的話,我寧願自己編寫這樣的class。特別地,對於WCF-WCF(Client和Service都是WCF),如果可能的話,讓定義Contract的Assembly在Service和contract共享,我想是最直接的方式。

  上面我們說所說的都是根據Service暴露出來的、以廠商中立方式體現的(比如XSD)Client端生成或者自行創建與之相對的Data type。但是對於下面這樣的場景,重建Data Type卻不是一個好的選擇:Client現在已經有一個Order class,而且很多的業務邏輯均依賴於這個class,現在需要調用一個現有的Order Processing Service對Order作某種處理,但是Service 的Order Type,說得更准確地,Service暴露出來的Order Data Contract和Client現有的Order class不太一致,很顯然在這種情況下,Client端部可能使用本地Order對象來調用該Service,因為Client提供的數據不符合該Data Contract,如果想上面講到了重新生成或者創建一個新的Order class,就意味著其他依賴於現有Order class的業務邏輯均會受其影響。所以,在這裡,我們需要WCF Data Contract提供給我們的另一種功能——適配功能:通過現有的CLR Type上添加或者改變DataContractAttribute 或者DataMemberAttribute的參數來使現有的CLR Type符合一個既定的Data Contract。究其本質,無論將CLR Type暴露成一個Neutral Contract也好,將CLR Type與既定的Neutral Contract進行適配也罷,這兩種功能都是等效的。

  接下來,我們就根據一個例子來討論WCF Data Contract如何將一個現有的CLR Type與一個既定的Neutral Data Contract匹配。

  Data Contract Mapping Mechanism

  通過上面的介紹,我們發現WCF Data Contract就如同一個適配器,彌合了 CLR Type和Neutral Contract的差異,很容易地實現了他們之間的匹配。接下來,我們就以一個實際的例子來介紹WCF DataContract的這種適配功能:通過DataContractAttribute的修飾,實現了將一個現有Data Type向一個既定的Neutral Data Contract進行適配,從而實現了對基於該Neutral Data Contract的Service 進行正常調用的目的。

  我們就以上面提到的Order Class為例,Service端的Order class最終暴露成一個以XSD表示的Neutral Contract:

  Order class:

  

  namespace Artech.DataContractVersioning.Service
{
[DataContract(Namespace="")]
public class Order
{
[DataMember(Order = 0)]
public Guid OrderID
{get;set;}

  [DataMember(Order = 1)]
public DateTime OrderDate
{ get; set; }

  [DataMember(Order = 2)]
public Guid SupplierID
{ get; set; }
}
}

  XSD:

  xmlns:xs="" xmlns:tns=""
xmlns:ser="">
namespace="" />

  public class CustomOrder
{
[DataMember(Order = 0, Name="OrderID")]
public Guid OrderNo
{ get; set; }

  [DataMember(Order = 2, Name = "SupplierID")]
public Guid SupplierNo
{ get; set; }

  [DataMember(Order = 1)]
public DateTime OrderDate
{ get; set; }

  [DataMember(Order = 3)]
public string ShippingAddress
{ get; set; }
}


通過在DataContractAttribute指定Name和Namespace使Data Contract和Namespace和既定的Contract相匹配,通過DataMemberAttribute的Name和Order參數是成員的名稱和次序與既定的Contract相匹配。


From:http://tw.wingwit.com/Article/program/net/201311/13263.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.