C# Attribute(特性)之---資料契約 [DataContract]
服務契約定義了遠端訪問物件和可供呼叫的方法,資料契約則是服務端和客戶端之間要傳送的自定義資料型別。
一旦宣告一個型別為DataContract,那麼該型別就可以被序列化在服務端和客戶端之間傳送,如下所示。
[DataContract]
public class UserInfo
{
//….
}
只有宣告為DataContract的型別的物件可以被傳送,且只有成員屬性會被傳遞,成員方法不會被傳遞。WCF對宣告為DataContract的型別提供更加細節的控制,可以把一個成員排除在序列化範圍以外,也就是說,客戶端程式不會獲得被排除在外的成員的任何資訊,包括定義和資料。預設情況下,所有的成員屬性都被排除在外,因此需要把每一個要傳送的成員宣告為DataMember,如下所示。
[DataContract]
public class UserInfo
{
[DataMember]
public string UserName
{
get;
set;
}
[DataMember]
public int Age
{
get;
set;
}
[DataMember]
public string Location
{
get;
set;
}
public string Zodiac
{
get;
set;
}
}
上面這段程式碼把UserInfo類宣告為DataContract,將UserName、Age、Location這3個屬性宣告為DataMember(資料成員)。Zodiac成員沒有被宣告為DataMember,因此在交換資料時,不會傳輸Zodiac的任何資訊。
DataContract也支援Name/Namespace屬性,如同ServiceContract,Name和Namespace可以自定義名稱和名稱空間,客戶端將使用自定義的名稱和名稱空間對DataContract型別進行訪問。
宣告為DataMember的成員也可以自定義客戶端可見的名稱,例如:
[DataMember(Name="Name")]
public string UserName
{
get;
set;
}
[DataMember(Name="Age")]
public int UserAge
{
get;
set;
}
除了Name和Namespace以外,DataMember還有以下引數,它們的含義分別如下。
(1)IsRequired:值為true時,要求序列化引擎檢查物件是否存在該值;若無,則會有異常丟擲。
(2)Order:bool型別值,值為true時,序列化和反序列化過程將會按成員定義的順序進行,這對依賴於成員位置的反序列化過程無比重要。
(3)EmitDefaultvalue:為成員屬性設定一個預設值。
一般情況下,將型別宣告為DataContract就可以滿足傳送的需求了,不過特殊情況是難以避免的,這時就需要對要傳送的SOAP訊息進行更加精確的控制,MessageContract可以滿足這種需求。
把一個型別宣告為MessageContract,意味著它可以被序列化為SOAP訊息,可以宣告型別的成員為SOAP訊息的各個部分,如Header、Body等,如下所示。
[MessageContract]
public class UserMessage
{
private string user = String.Empty;
private string authKey = String.Empty;
[MessageBodyMember(
Name = "UserName",
Namespace = "http://www.wcf.com")]
public string User
{
get { return user; }
set { user = value; }
}
[MessageHeader(
Name = "AuthKey",
Namespace = "http://www.wcf.com",
MustUnderstand = true
)]
public string AuthKey
{
get { return authKey; }
set { this.authKey = value; }
}
}
User成員被宣告為MessageBody(訊息體)的一個成員,AuthKey被宣告為訊息頭(MessageHeader)的一個成員。這個類將可以生成如下的SOAP訊息。
<s:Envelope>
<s:Header>
<a:Action s:mustUnderstand="1">http://UserMessage/Action</a:Action>
<h:AuthKey s:mustUnderstand="1" xmlns:h="http://www.wcf.com">xxxx</h:AuthKey>
</s:Header>
<s:Body>
<UserMessage xmlns="Microsoft.WCF.Documentation">
<User xmlns="http://www.wcf.com">abcd</User>
</UserMessage>
</s:Body>
</s:Envelope>
MessageHeader中,MustUnderstand引數表示讀取該頭的程式必須能夠識別頭的內容,否則不能繼續處理。Name/Namespace的作用與前面的元素相同。另有Relay引數,若為true,頭的內容被接收到以後會在響應訊息中回發給訊息傳送端。