Поделиться через


Эквивалентность контракта данных

Чтобы клиент успешно отправлял данные определенного типа в службу или службу для успешной отправки данных клиенту, тип отправки не обязательно должен существовать на принимающем конце. Единственное требование заключается в том, что контракты данных обоих типов эквивалентны. (Иногда строгая эквивалентность не требуется, как указано в разделе Управление версиями контракта данных.)

Для того чтобы контракты данных были эквивалентными, они должны иметь то же пространство имен и имя. Кроме того, каждый член данных на одной стороне должен иметь эквивалентный элемент данных на другой стороне.

Для эквивалентных элементов данных они должны иметь то же имя. Кроме того, они должны представлять тот же тип данных; То есть их контракты данных должны быть эквивалентными.

Замечание

Обратите внимание, что имена контрактов данных и пространства имен, а также имена элементов данных чувствительны к регистру.

Дополнительные сведения о именах контрактов данных и пространствах имен, а также именах элементов данных см. в разделе "Имена контрактов данных".

Если два типа существуют на одной стороне (отправитель или получатель) и их контракты данных не эквивалентны (например, они имеют разные члены данных), то не следует предоставлять им то же имя и пространство имен. Это может привести к возникновению исключений.

Контракты данных для следующих типов эквивалентны:

[DataContract]
public class Customer
{
    [DataMember]
    public string fullName;

    [DataMember]
    public string telephoneNumber;
}

[DataContract(Name = "Customer")]
public class Person
{
    [DataMember(Name = "fullName")]
    private string nameOfPerson;

    private string address;

    [DataMember(Name = "telephoneNumber")]
    private string phoneNumber;
}
<DataContract()> _
Public Class Customer

    <DataMember()> _
    Public fullName As String

    <DataMember()> _
    Public telephoneNumber As String
End Class

<DataContract(Name:="Customer")> _
Public Class Person

    <DataMember(Name:="fullName")> _
    Private nameOfPerson As String

    Private address As String

    <DataMember(Name:="telephoneNumber")> _
    Private phoneNumber As String
End Class

Порядок элементов данных и эквивалентность контракта данных

Использование свойства Order класса DataMemberAttribute может повлиять на эквивалентность контракта данных. Контракты данных должны иметь элементы, которые отображаются в том же порядке, чтобы быть эквивалентными. Порядок по умолчанию является алфавитным. Дополнительные сведения см. в разделе "Порядок элементов данных".

Например, следующий код приводит к эквивалентным контрактам данных.

[DataContract(Name = "Coordinates")]
public class Coords1
{
    [DataMember]
    public int X;
    [DataMember]
    public int Y;
    // Order is alphabetical (X,Y).
}

[DataContract(Name = "Coordinates")]
public class Coords2
{
    [DataMember]
    public int Y;
    [DataMember]
    public int X;
    // Order is alphabetical (X,Y), equivalent
    // to the preceding code.
}

[DataContract(Name = "Coordinates")]
public class Coords3
{
    [DataMember(Order = 2)]
    public int Y;
    [DataMember(Order = 1)]
    public int X;
    // Order is according to the Order property (X,Y),
    // equivalent to the preceding code.
}
<DataContract(Name:="Coordinates")> _
Public Class Coords1
    <DataMember()> _
    Public X As Integer
    <DataMember()> _
    Public Y As Integer
    ' Order is alphabetical (X,Y).
End Class

<DataContract(Name:="Coordinates")> _
Public Class Coords2

    <DataMember()> _
    Public Y As Integer
    <DataMember()> _
    Public X As Integer
    ' Order is alphabetical (X,Y), equivalent 
    ' to the preceding code.
End Class

<DataContract(Name:="Coordinates")> _
Public Class Coords3
    <DataMember(Order:=2)> _
    Public Y As Integer
    <DataMember(Order:=1)> _
    Public X As Integer
    ' Order is according to the Order property (X,Y), 
    ' equivalent to the preceding code.
End Class

Однако следующее не приводит к эквивалентному договору о данных.

[DataContract(Name = "Coordinates")]
public class Coords4
{
    [DataMember(Order = 1)]
    public int Y;
    [DataMember(Order = 2)]
    public int X;
    // Order is according to the Order property (Y,X),
    // different from the preceding code.
}
<DataContract(Name:="Coordinates")> _
Public Class Coords4

    <DataMember(Order:=1)> _
    Public Y As Integer
    <DataMember(Order:=2)> _
    Public X As Integer
    ' Order is according to the Order property (Y,X), 
    ' different from the preceding code.
End Class

Наследование, интерфейсы и эквивалентность контракта данных

При определении эквивалентности контракт данных, наследуемый от другого контракта данных, обрабатывается так, как если бы он был только одним контрактом данных, который включает все элементы данных из базового типа. Помните, что порядок элементов данных должен соответствовать и что элементы базового типа предшествуют производным элементам типа в порядке. Кроме того, если в следующем примере кода два члена данных имеют одно и то же значение порядка, порядок для этих элементов данных является алфавитным. Дополнительные сведения см. в разделе "Порядок элементов данных".

В следующем примере контракт данных для типа Employee эквивалентен контракту данных для типа Worker.

[DataContract]
public class Person
{
    [DataMember]
    public string name;
}
[DataContract]
public class Employee : Person
{
    [DataMember]
    public int department;
    [DataMember]
    public string title;
    [DataMember]
    public int salary;
}
// Order is "name", "department", "salary", "title"
// (base class first, then alphabetical).

[DataContract(Name = "Employee")]
public class Worker
{
    [DataMember(Order = 1)]
    public string name;
    [DataMember(Order = 2)]
    public int department;
    [DataMember(Order = 2)]
    public string title;
    [DataMember(Order = 2)]
    public int salary;
}
// Order is "name", "department", "salary", "title"
// (Order=1 first, then Order=2 in alphabetical order),
// which is equivalent to the Employee order}.
<DataContract()> _
Public Class Person
    <DataMember()> Public name As String
End Class

<DataContract()> _
Public Class Employee
    Inherits Person
    <DataMember()> Public department As Integer
    <DataMember()> Public title As String
    <DataMember()> Public salary As Integer
End class

' Order is "name", "department", "salary", "title" 
' (base class first, then alphabetical).

<DataContract(Name:="Employee")> _
Public Class Worker

    <DataMember(Order:=1)> _
    Public name As String
    <DataMember(Order:=2)> _
    Public department As Integer
    <DataMember(Order:=2)> _
    Public title As String
    <DataMember(Order:=2)> _
    Public salary As Integer
End Class
' Order is "name", "department", "salary", "title" 
' (Order=1 first, then Order=2 in alphabetical order), 
' which is equivalent to the Employee order}.

При передаче параметров и возвращаемых значений между клиентом и службой контракт данных из базового класса не может быть отправлен, когда принимающей конечной точке ожидается контракт данных из производного класса. Это соответствует объектно-ориентированному принципу программирования. В предыдущем примере объект типа Person не может быть отправлен, когда Employee ожидается.

Контракт данных из производного класса можно отправить, когда ожидается контракт данных из базового класса, но только если принимающая конечная точка "знает" о производном типе с помощью KnownTypeAttribute. Дополнительные сведения см. в разделе "Известные типы контракта данных". В предыдущем примере объект типа Employee можно отправить, если Person ожидается, но только если код получателя использует KnownTypeAttribute его для включения в список известных типов.

При передаче параметров и возвращаемых значений между приложениями, если ожидаемый тип является интерфейсом, он эквивалентен ожидаемому типу типа Object. Поскольку каждый тип в конечном счете является производным от Object, каждый контракт данных в конечном счете является производным от контракта данных для Object. Таким образом, любой тип контракта данных может передаваться при ожидаемом интерфейсе. Для успешной работы с интерфейсами требуются дополнительные шаги; Дополнительные сведения см. в разделе "Известные типы контракта данных".

См. также