Równoważność kontraktów danych

Aby klient mógł pomyślnie wysłać dane określonego typu do usługi lub usługi w celu pomyślnego wysłania danych do klienta, typ wysłany nie musi istnieć na końcu odbierania. Jedynym wymaganiem jest to, że kontrakty danych obu typów są równoważne. (Czasami nie jest wymagana ścisła równoważność, zgodnie z opisem w temacie Przechowywanie wersji kontraktu danych).

Aby kontrakty danych były równoważne, muszą mieć taką samą przestrzeń nazw i nazwę. Ponadto każdy element członkowski danych po jednej stronie musi mieć równoważny element członkowski danych po drugiej stronie.

Aby składowe danych były równoważne, muszą mieć taką samą nazwę. Ponadto muszą reprezentować ten sam typ danych; oznacza to, że ich kontrakty danych muszą być równoważne.

Uwaga

Należy pamiętać, że nazwy kontraktów danych i przestrzenie nazw, a także nazwy składowych danych, są uwzględniane wielkości liter.

Aby uzyskać więcej informacji na temat nazw kontraktów danych i przestrzeni nazw, a także nazw elementów członkowskich danych, zobacz Nazwy kontraktów danych.

Jeśli dwa typy istnieją po tej samej stronie (nadawca lub odbiorca), a ich kontrakty danych nie są równoważne (na przykład mają różne elementy członkowskie danych), nie należy nadawać im tej samej nazwy i przestrzeni nazw. Może to spowodować zgłoszenie wyjątków.

Kontrakty danych dla następujących typów są równoważne:

[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

Kolejność elementów członkowskich danych i równoważność kontraktu danych

Order Użycie właściwości klasy może mieć wpływ na równoważność kontraktu DataMemberAttribute danych. Kontrakty danych muszą mieć elementy członkowskie, które są wyświetlane w tej samej kolejności, aby być równoważne. Kolejność domyślna to alfabetyczna. Aby uzyskać więcej informacji, zobacz Data Member Order (Kolejność składowych danych).

Na przykład poniższy kod powoduje wykonanie równoważnych kontraktów danych.

[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

Jednak następujące elementy nie powodują wystąpienia równoważnego kontraktu danych.

[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

Dziedziczenie, interfejsy i równoważność kontraktu danych

Podczas określania równoważności kontrakt danych dziedziczący z innego kontraktu danych jest traktowany tak, jakby był to tylko jeden kontrakt danych zawierający wszystkie elementy członkowskie danych z typu podstawowego. Należy pamiętać, że kolejność składowych danych musi być zgodna i że składowe typu podstawowego poprzedzają pochodne składowe typu w kolejności. Ponadto jeśli, podobnie jak w poniższym przykładzie kodu, dwa składowe danych mają tę samą wartość zamówienia, kolejność tych elementów członkowskich danych jest alfabetyczna. Aby uzyskać więcej informacji, zobacz Data Member Order (Kolejność składowych danych).

W poniższym przykładzie kontrakt danych dla typu Employee jest odpowiednikiem kontraktu danych dla typu 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}.

Podczas przekazywania parametrów i zwracanych wartości między klientem a usługą nie można wysłać kontraktu danych z klasy bazowej, gdy odbierający punkt końcowy oczekuje kontraktu danych z klasy pochodnej. Jest to zgodne z obiektowymi założeniami programowania. W poprzednim przykładzie nie można wysłać obiektu typu Person , gdy obiekt jest oczekiwany Employee .

Kontrakt danych z klasy pochodnej może być wysyłany, gdy oczekiwano kontraktu danych z klasy bazowej, ale tylko wtedy, gdy punkt końcowy odbierający "wie" o typie pochodnym KnownTypeAttributeprzy użyciu klasy . Aby uzyskać więcej informacji, zobacz Znane typy kontraktów danych. W poprzednim przykładzie obiekt typu Employee można wysłać, gdy Person jest oczekiwany, ale tylko wtedy, gdy kod odbiorcy używa KnownTypeAttribute elementu , aby uwzględnić go na liście znanych typów.

Podczas przekazywania parametrów i zwracania wartości między aplikacjami, jeśli oczekiwany typ jest interfejsem, jest to odpowiednik oczekiwanego Objecttypu typu . Ponieważ każdy typ ostatecznie pochodzi z Object, każdy kontrakt danych ostatecznie pochodzi z kontraktu danych dla .Object W związku z tym każdy typ kontraktu danych można przekazać, gdy interfejs jest oczekiwany. Aby pomyślnie pracować z interfejsami, wymagane są dodatkowe kroki; Aby uzyskać więcej informacji, zobacz Znane typy kontraktów danych.

Zobacz też