Использование контрактов данныхUsing Data Contracts

Контракт данных - формальное соглашение между службой и клиентом, абстрактно описывающее данные, обмен которыми происходит.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, такие как Integer и String, а также определенные типы, которые обрабатываются как примитивы, такие как DateTime и XmlElement, могут быть сериализованы без дополнительной обработки и рассматриваются как имеющие контракты данных по умолчанию.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 Serializer.For 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. Все открытые свойства чтения/записи и поля типа сериализуются.All public read/write properties and fields of the type are serialized. Можно исключать члены из сериализации с помощью IgnoreDataMemberAttribute.You can opt out members from serialization by using the IgnoreDataMemberAttribute. Также можно явно создавать контракт данных с помощью атрибутов DataContractAttribute и DataMemberAttribute .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. Данный атрибут может быть применен к классам, структурам и перечислениям.This attribute can be applied to classes, structures, and enumerations. После этого необходимо применить атрибут DataMemberAttribute к каждому члену типа контракта данных, чтобы указать, что он является членом данных, который необходимо сериализовать.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

В следующем примере показано явное применение атрибутов ServiceContractAttribute и OperationContractAttribute к контракту службы (интерфейсу).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.PurchaseOrder путем применения атрибутов DataContractAttribute и 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. Сюда входят типы, которые не отмечены ни одним из атрибутов DataContractAttribute, SerializableAttribute, CollectionDataContractAttribute, EnumMemberAttribute или отмечены как сериализуемые любыми другими способами (например, 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 применим к полям и свойствам.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.

  • Во время сериализации вначале создается неинициализированный объект без вызова каких-либо конструкторов типа.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 Serializer.For 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