在我們看來
這實際上體現了兩者相互交互的問題
我們知道SOA一個主要的目標就是促進不同技術平台的互操作
SOA中的一個Service由一組相關的Operation來構成
上面我們說了Service Contract是以一種廠商中立的形式描述體現為某種模式的消極交互
概括的說
Contract in WCF
上面我們實際上是在一個廠商中立的前提下探討Contract
比如我們一個運用了DataContractAttribute和DataMemberAttribute的Order class
namespace Artech
{
[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; }
}
}
就可以轉變成另一種廠商中立的
xmlns:xs=
xmlns:tns=
xmlns:ser=
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:ser="">
{
[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