Datenvertragsäquivalenz

Damit ein Client erfolgreich Daten eines bestimmten Typs an einen Dienst sendet oder ein Dienst erfolgreich Daten an einen Client sendet, muss der gesendete Typ nicht unbedingt an der Empfängerseite vorhanden sein. Die einzige Anforderung ist, dass die Datenverträge beider Typen äquivalent sind. (Manchmal ist strenge Äquivalenz nicht erforderlich, siehe Datenvertragsversionsverwaltung.)

Die Äquivalenz von Datenverträgen wird durch denselben Namespace und Namen gewährleistet. Darüber hinaus muss jeder Datenmember auf einer Seite über einen entsprechenden Datenmember auf der anderen Seite verfügen.

Die Äquivalenz von Datenmembern wird durch denselben Namen gewährleistet. Darüber hinaus müssen sie denselben Datentyp aufweisen; das heißt, ihre Datenverträge müssen äquivalent sein.

Hinweis

Bei Datenvertragsnamen und Namespaces sowie Datenmembernamen ist Groß-\/Kleinschreibung zu beachten.

Weitere Informationen finden Sie unter zu Datenvertragsnamen und Namespaces sowie zu Datenmembernamen finden Sie unter Datenvertragsnamen.

Sind zwei Typen auf derselben Seite vorhanden (Absender oder Empfänger) und sind die Datenverträge nicht äquivalent (wenn sie beispielsweise unterschiedliche Datenmember besitzen), sollten sie nicht denselben Name und denselben Namespace erhalten. Falls Sie doch denselben Namen bzw. Namespace zuweisen, werden möglicherweise Ausnahmen ausgelöst.

Die Datenverträge für die folgenden Typen sind äquivalent:

[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

Datenmemberreihenfolge und Datenvertragsäquivalenz

Die Verwendung der Order-Eigenschaft der DataMemberAttribute-Klasse wirkt sich unter Umständen auf die Äquivalenz des Datenvertrags aus. Die Datenverträge sind nur äquivalent, wenn sie über Member verfügen, die in der gleichen Reihenfolge angezeigt werden. Die Standardreihenfolge ist alphabetisch. Weitere Informationen finden Sie unter Datenmember-Reihenfolge.

Zum Beispiel führt der folgende Code zu äquivalenten Datenverträgen.

[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

Folgendes führt jedoch nicht zu einem äquivalenten Datenvertrag.

[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

Vererbung, Schnittstellen und Datenvertragsäquivalenz

Beim Bestimmen der Äquivalenz wird ein Datenvertrag, der von einem anderen Datenvertrag erbt, so behandelt, als ob es sich nur um einen Datenvertrag mit allen Datenmembern vom Basistyp handelt. Die Reihenfolge der Datenmember muss übereinstimmen, und die Basistypmember müssen in der Reihenfolge vor den abgeleiteten Typmembern stehen. Verfügen zwei Datenmember &#8211; wie im folgenden Codesbeispiel &#8211; über denselben Reihenfolgenwert, werden diese Datenmember darüber hinaus alphabetisch sortiert. Weitere Informationen finden Sie unter Datenmember-Reihenfolge.

Im folgenden Beispiel entspricht der Datenvertrag für den Typ Employee dem Datenvertrag für den Typ 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}.

Beim Übergeben von Parametern und der Rückgabe von Werten zwischen einem Client und einem Dienst kann ein Datenvertrag von einer Basisklasse nicht gesendet werden, wenn der empfangende Endpunkt einen Datenvertrag von einer abgeleiteten Klasse erwartet. Dies stimmt mit objektorientierten Programmierungsgrundsätzen überein. Im vorherigen Beispiel kann ein Objekt vom Typ Person nicht gesendet werden, wenn Employee erwartet wird.

Ein Datenvertrag von einer abgeleiteten Klasse kann gesendet werden, wenn ein Datenvertrag von einer Basisklasse erwartet wird. Dies ist jedoch nur möglich, falls der empfangende Endpunkt unter Verwendung von KnownTypeAttribute über den abgeleiteten Typen "informiert" ist. Weitere Informationen finden Sie unter Bekannte Typen in Datenverträgen. Im vorangegangenen Beispiel kann ein Objekt vom Typ Employee gesendet werden, wenn eine Person erwartet wird. Dies ist jedoch nur möglich, falls der Empfängercode KnownTypeAttribute verwendet, um es in die Liste der bekannten Typen aufzunehmen.

Beim Übergeben von Parametern und Rückgabewerten zwischen Anwendungen entspricht der erwartete Typ (sofern es sich dabei um eine Schnittstelle handelt) dem erwarteten Typ Object. Da jeder Typ letztlich von Object abgeleitet wird, wird jeder Datenvertrag letztlich vom Datenvertrag für Object abgeleitet. So kann jeder Datenvertragstyp übergeben werden, wenn eine Schnittstelle erwartet wird. Für eine erfolgreiche Arbeit mit Schnittstellen sind zusätzliche Schritte erforderlich. Weitere Informationen hierzu finden Sie unter Bekannte Typen in Datenverträgen.

Siehe auch

DataContractAttribute
DataMemberAttribute
Datenmember-Reihenfolge
Bekannte Typen in Datenverträgen
Datenvertragsnamen