使用資料合約Using Data Contracts

資料合約 」(Data Contract) 是服務與用戶端之間的正式合約,其中會抽象地描述要交換的資料。A data contract is a formal agreement between a service and a client that abstractly describes the data to be exchanged. 也就是說,若要進行通訊,用戶端與服務並不需要共用相同的型別,而只需要共用相同的資料合約。That is, to communicate, the client and the service do not have to share the same types, only the same data contracts. 資料合約會針對每個參數或傳回型別精確地定義哪些資料要序列化 (變成 XML) 才能進行交換。A data contract precisely defines, for each parameter or return type, what data is serialized (turned into XML) to be exchanged.

資料合約基本概念Data Contract Basics

Windows Communication Foundation (WCF) 會使用序列化引擎預設會呼叫資料合約序列化程式序列化和還原序列化 (將它與 XML) 的資料。Windows Communication Foundation (WCF) uses a serialization engine called the Data Contract Serializer by default to serialize and deserialize data (convert it to and from XML). 所有.NET Framework 基本型別,例如整數和字串,以及視為基本類型,例如特定型別DateTimeXmlElement,沒有其他準備可以加以序列化,並會被視為具有預設的資料合約。All .NET Framework primitive types, such as integers and strings, as well as certain types treated as primitives, such as DateTime and XmlElement, can be serialized with no other preparation and are considered as having default data contracts. 許多.NET Framework 型別也有現有的資料合約。Many .NET Framework types also have existing data contracts. 如需可序列化型別的完整清單,請參閱 Types Supported by the Data Contract SerializerFor a full list of serializable types, see Types Supported by the Data Contract Serializer.

您建立的新複雜型別必須具有已針對其所定義的資料合約,才能夠進行序列化。New complex types that you create must have a data contract defined for them to be serializable. 根據預設, DataContractSerializer 會推斷資料合約,並且會序列化所有公開可見的型別。By default, the DataContractSerializer infers the data contract and serializes all publicly visible types. 型別的所有公用讀取/寫入屬性 (Property) 和欄位都會序列化。All public read/write properties and fields of the type are serialized. 您可以藉由使用 IgnoreDataMemberAttribute,選擇不序列化成員。You can opt out members from serialization by using the IgnoreDataMemberAttribute. 您也可以使用 DataContractAttributeDataMemberAttribute 屬性 (Attribute) 明確建立資料合約。You can also explicitly create a data contract by using DataContractAttribute and DataMemberAttribute attributes. 通常將 DataContractAttribute 屬性套用至該型別即可達成這點。This is normally done by applying the DataContractAttribute attribute to the type. 這個屬性可以套用至類別、結構和列舉型別 (Enumeration)。This attribute can be applied to classes, structures, and enumerations. 然後, DataMemberAttribute 屬性必須套用至資料合約型別的各個成員,以表示其為「 資料成員」(Data Member),也就是這個成員應該要加以序列化。The DataMemberAttribute attribute must then be applied to each member of the data contract type to indicate that it is a data member, that is, it should be serialized. 如需詳細資訊,請參閱 < 可序列化型別For more information, see Serializable Types.

範例Example

下列範例會示範已經明確套用 ServiceContractAttributeOperationContractAttribute 屬性的服務合約 (介面)。The following example shows a service contract (an interface) to which the ServiceContractAttribute and OperationContractAttribute attributes have been explicitly applied. 此範例會示範基本型別不需要資料合約,而複雜型別則需要。The example shows that primitive types do not require a data contract, while a complex type does.

[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.PurchaseOrderDataContractAttribute 屬性套用至類別及其成員,以便建立 DataMemberAttribute 型別的資料合約。The following example shows how a data contract for the MyTypes.PurchaseOrder type is created by applying the DataContractAttribute and DataMemberAttribute attributes to the class and its members.

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 

注意Notes

下列注意事項提供在建立資料合約時的考慮項目:The following notes provide items to consider when creating data contracts:

  • IgnoreDataMemberAttribute 屬性只有在搭配未標記的型別使用時才會被接受。The IgnoreDataMemberAttribute attribute is only honored when used with unmarked types. 其中包含未使用 DataContractAttributeSerializableAttributeCollectionDataContractAttributeEnumMemberAttribute 屬性其中一個所標記的型別,或未透過任何其他方式 (例如 IXmlSerializable) 標記為可序列化的型別。This includes types that are not marked with one of the DataContractAttribute, SerializableAttribute, CollectionDataContractAttribute, or EnumMemberAttribute attributes, or marked as serializable by any other means (such as IXmlSerializable).

  • 您可以將 DataMemberAttribute 屬性 (Attribute) 套用至欄位和屬性 (Property)。You can apply the DataMemberAttribute attribute to fields, and properties.

  • 成員存取層級 (內部、私密、保護或公用) 不會以任何形式影響資料合約。Member accessibility levels (internal, private, protected, or public) do not affect the data contract in any way.

  • DataMemberAttribute 屬性在套用至靜態成員時會遭到忽略。The DataMemberAttribute attribute is ignored if it is applied to static members.

  • 取得屬性 (property-get) 的程式碼會在進行序列化時呼叫,以便讓屬性資料成員取得要進行序列化之屬性的值。During serialization, property-get code is called for property data members to get the value of the properties to be serialized.

  • 在進行還原序列化時會先建立未初始化的物件,而不會呼叫該型別上的任何建構函式 (Constructor)。During deserialization, an uninitialized object is first created, without calling any constructors on the type. 接下來,所有的資料成員都會還原序列化。Then all data members are deserialized.

  • 設定屬性 (property-set) 的程式碼會在進行還原序列化時呼叫,以便讓屬性資料成員設定要進行還原序列化之屬性的值。During deserialization, property-set code is called for property data members to set the properties to the value being deserialized.

  • 若是有效的資料合約,該資料合約肯定是可能會序列化其所有資料成員。For a data contract to be valid, it must be possible to serialize all of its data members. 如需可序列化型別的完整清單,請參閱 Types Supported by the Data Contract SerializerFor a full list of serializable types, see Types Supported by the Data Contract Serializer.

    對於泛型型別的處理方式與非泛型型別完全相同。Generic types are handled in exactly the same way as non-generic types. 對於泛型參數沒有特殊的需求。There are no special requirements for generic parameters. 以下列型別為例:For example, consider the following type.

[DataContract]
public class MyGenericType1<T>
{
    // Code not shown.
}
<DataContract()>  _
Public Class MyGenericType1(Of T)
    ' Code not shown.
End Class

無論用於泛型型別參數 (T) 的型別是否為可序列化的型別,這個型別都是可序列化的型別。This type is serializable whether the type used for the generic type parameter (T) is serializable or not. 由於其一定可以序列化所有的資料成員,所以下列型別只有在泛型型別參數也屬於可序列化時才能進行序列化,如下列程式碼所示。Because it must be possible to serialize all data members, the following type is serializable only if the generic type parameter is also serializable, as shown in the following code.

[DataContract]
public class MyGenericType2<T>
{
    [DataMember]
    T theData;
}
<DataContract()>  _
Public Class MyGenericType2(Of T)
    <DataMember()>  _
    Dim theData As T
End Class 

如需定義資料合約的 WCF 服務完整程式碼範例,請參閱 Basic Data Contract 範例。For a complete code sample of a WCF service that defines a data contract see the Basic Data Contract sample.

另請參閱See also