數據合約是服務與客戶端之間的正式合約,其會以抽象方式描述要交換的數據。 也就是說,若要通訊,客戶端和服務不需要共用相同的類型,只有相同的數據合約。 資料合約會針對每個參數或傳回類型,精確定義被序列化(轉換成 XML)來交換的資料。
數據合約基本概念
Windows Communication Foundation (WCF) 預設會使用稱為「資料契約序列化工具」的序列化引擎來序列化及反序列化資料(將資料轉換成 XML 或從 XML 轉換)。 所有 .NET Framework 基本類型,例如整數和字串,以及視為基本類型的特定類型,例如 DateTime 和 XmlElement,都可以以沒有其他準備進行串行化,並被視為具有默認數據合約。 許多 .NET Framework 類型也有現有的數據合約。 如需可串行化類型的完整清單,請參閱 數據合約串行化程式支援的類型。
您建立的新複雜型別必須定義數據合約,才能串行化。 根據預設,會 DataContractSerializer 推斷數據合約,並串行化所有公開可見的類型。 型別的所有公用讀取/寫入屬性和欄位都會被序列化。 您可以使用 IgnoreDataMemberAttribute 來取消成員的序列化。 您也可以使用 DataContractAttribute 和 DataMemberAttribute 屬性明確建立數據合約。 這通常是藉由將 DataContractAttribute 屬性套用至類型來完成。 這個屬性可以套用至類別、結構和列舉。 DataMemberAttribute然後,屬性必須套用至數據合約類型的每個成員,以指出它是數據成員,也就是說,它應該串行化。 如需詳細資訊,請參閱 可串行化類型。
範例
下列範例顯示已明確套用ServiceContractAttribute和OperationContractAttribute屬性的服務合約(介面)。 此範例顯示基本型別不需要資料合約,而複雜型別則為 。
[ServiceContract]
public interface ISampleInterface
{
// No data contract is required since both the parameter
// and return types are primitive types.
[OperationContract]
double SquareRoot(int root);
// No Data Contract required because both parameter and return
// types are marked with the SerializableAttribute attribute.
[OperationContract]
System.Drawing.Bitmap GetPicture(System.Uri pictureUri);
// The MyTypes.PurchaseOrder is a complex type, and thus
// requires a data contract.
[OperationContract]
bool ApprovePurchaseOrder(MyTypes.PurchaseOrder po);
}
<ServiceContract()> _
Public Interface ISampleInterface
' No data contract is required since both the parameter and return
' types are both primitive types.
<OperationContract()> _
Function SquareRoot(ByVal root As Integer) As Double
' No Data Contract required because both parameter and return
' types are marked with the SerializableAttribute attribute.
<OperationContract()> _
Function GetPicture(ByVal pictureUri As System.Uri) As System.Drawing.Bitmap
' The MyTypes.PurchaseOrder is a complex type, and thus
' requires a data contract.
<OperationContract()> _
Function ApprovePurchaseOrder(ByVal po As MyTypes.PurchaseOrder) As Boolean
End Interface
下列範例示範如何透過將 MyTypes.PurchaseOrder
及 DataContractAttribute 屬性套用到類別及其成員來建立 DataMemberAttribute 型別的資料合約。
namespace MyTypes
{
[DataContract]
public class PurchaseOrder
{
private int poId_value;
// Apply the DataMemberAttribute to the property.
[DataMember]
public int PurchaseOrderId
{
get { return poId_value; }
set { poId_value = value; }
}
}
}
Namespace MyTypes
<System.Runtime.Serialization.DataContractAttribute()> _
Public Class PurchaseOrder
Private poId_value As Integer
' Apply the DataMemberAttribute to the property.
<DataMember()> _
Public Property PurchaseOrderId() As Integer
Get
Return poId_value
End Get
Set
poId_value = value
End Set
End Property
End Class
End Namespace
註釋
下列附注提供建立資料契約時要考慮的事項:
IgnoreDataMemberAttribute 屬性只有在搭配未標記的類型時才會生效。 這包括類型未使用DataContractAttribute、SerializableAttribute、CollectionDataContractAttribute或EnumMemberAttribute屬性標記,或以任何其他方式(例如IXmlSerializable)標示為可串行化的。
您可以將DataMemberAttribute屬性套用至欄位和屬性。
成員存取層級(內部、私有、受保護或公共)不會以任何方式影響資料契約。
DataMemberAttribute如果屬性套用至靜態成員,則會予以忽略。
在串行化期間,會針對屬性數據成員呼叫 property-get 程式代碼,以取得要串行化之屬性的值。
在反序列化過程中,會先建立一個未經初始化的物件,並且不會在該型別上呼叫任何建構函式。 然後所有資料成員都會被反序列化。
在還原串行化期間,會呼叫屬性集程式代碼,讓屬性數據成員將屬性設定為要還原串行化的值。
若要讓數據合約有效,必須能夠串行化其所有數據成員。 如需可串行化類型的完整清單,請參閱 數據合約串行化程式支援的類型。
泛型型別的處理方式與非泛型型別完全相同。 泛型參數沒有特殊需求。 例如,請考慮下列類型。
[DataContract]
public class MyGenericType1<T>
{
// Code not shown.
}
<DataContract()> _
Public Class MyGenericType1(Of T)
' Code not shown.
End Class
無論用於泛型類型參數的T
類型是否可序列化,此類型始終是可序列化的。 因為必須能夠串行化所有數據成員,所以只有在泛型型別參數也是可串行化時,才能串行化下列類型,如下列程式碼所示。
[DataContract]
public class MyGenericType2<T>
{
[DataMember]
T theData;
}
<DataContract()> _
Public Class MyGenericType2(Of T)
<DataMember()> _
Dim theData As T
End Class
如需定義數據合約之 WCF 服務的完整程式碼範例,請參閱 基本數據合約 範例。