Использование контрактов данных
Контракт данных - формальное соглашение между службой и клиентом, абстрактно описывающее данные, обмен которыми происходит. Это значит, что для взаимодействия клиент и служба не обязаны совместно использовать одни и те же типы, достаточно совместно использовать одни и те же контракты данных. Контракт данных для каждого параметра и возвращаемого типа четко определяет, какие данные сериализуются (превращаются в XML) для обмена.
Основные сведения о контрактах данных
Windows Communication Foundation (WCF) использует модуль сериализации, называемый сериализатором контракта данных по умолчанию для сериализации и десериализации данных (преобразование в XML и из него). Все платформа .NET Framework примитивные типы, такие как целые числа и строки, а также определенные типы, которые рассматриваются как примитивы, например DateTime иXmlElement, могут быть сериализованы без другой подготовки и считаются контрактами данных по умолчанию. Многие платформа .NET Framework типы также имеют существующие контракты данных. Полный список сериализуемых типов см. в разделе Types Supported by the Data Contract Serializer.
Для сериализации новых созданных сложных типов необходимо определить контракты данных. По умолчанию 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, возвращающий значения сериализуемых свойств.
Во время сериализации вначале создается неинициализированный объект без вызова каких-либо конструкторов типа. Затем десериализуются все члены данных.
Во время десериализации для членов данных свойств вызывается код property-set, задающий значения сериализуемым свойствам.
Чтобы контракт данных был допустимым, все его члены данных должны быть сериализуемыми. Полный список сериализуемых типов см. в разделе Types Supported by the Data Contract Serializer.
Универсальные типы обрабатываются таким же образом, как и неуниверсальные. Для универсальных параметров нет особых требований. Например, рассмотрим следующий тип:
[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, которая определяет контракт данных, см. в примере Basic Data Contract .
См. также
- DataMemberAttribute
- DataContractAttribute
- Сериализуемые типы
- Имена контрактов данных
- Эквивалентность контрактов данных
- Порядок членов данных
- Известные типы контрактов данных
- Контракты данных, совместимые с любыми будущими изменениями
- Управление версиями контракта данных
- Обратные вызовы сериализации, независимые от версий
- Значения членов данных по умолчанию
- Types Supported by the Data Contract Serializer
- Практическое руководство. Создание базового контракта данных для класса или структуры