Partekatu bidez


Equivalencia del contrato de datos

Para que un cliente envíe correctamente datos de un tipo determinado a un servicio o un servicio para enviar correctamente datos a un cliente, el tipo enviado no tiene que existir necesariamente en el extremo receptor. El único requisito es que los contratos de datos de ambos tipos sean equivalentes. (A veces, no se requiere una equivalencia estricta, como se describe en Versionado del contrato de datos.)

Para que los contratos de datos sean equivalentes, deben incluir el mismo espacio de nombres y nombre. Además, cada miembro de datos de un lado debe tener un miembro de datos equivalente en el otro lado.

Para que los miembros de datos sean equivalentes, deben tener el mismo nombre. Además, deben representar el mismo tipo de datos; es decir, sus contratos de datos deben ser equivalentes.

Nota:

Tenga en cuenta que los nombres y espacios de nombres de contrato de datos, así como los nombres del miembros de datos, distinguen entre mayúsculas y minúsculas.

Para más información sobre los nombres y los espacios de nombres de contrato de datos, así como los nombres de los miembros de datos, consulte Nombres de contratos de datos.

Si dos tipos existen en el mismo lado (remitente o receptor) y sus contratos de datos no son equivalentes (por ejemplo, tienen diferentes miembros de datos), no debería darles el mismo nombre y espacio de nombres. Si lo hace, pueden iniciarse excepciones.

Los contratos de datos para los siguientes tipos son equivalentes:

[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

Orden del miembro de datos y equivalencia del contrato de datos

El uso de la propiedad Order de la clase DataMemberAttribute puede afectar la equivalencia del contrato de datos. Los contratos de datos deben tener miembros que aparezcan en el mismo orden para ser equivalentes. El orden predeterminado es alfabético. Para obtener más información, consulte Orden de los miembros de datos.

Por ejemplo, el código siguiente da como resultado contratos de datos equivalentes.

[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

Sin embargo, lo siguiente no da lugar a un contrato de datos equivalente.

[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

Herencia, interfaces y equivalencia de contratos de datos

Al determinar la equivalencia, un contrato de datos que hereda de otro contrato de datos se trata como si fuera solo un contrato de datos que incluya todos los miembros de datos del tipo base. Tenga en cuenta que el orden de los miembros de datos debe coincidir y que los miembros de tipo base preceden a los miembros de tipo derivados en el orden. Además, si, como en el ejemplo de código siguiente, dos miembros de datos tienen el mismo valor de orden, el orden para esos miembros de datos es alfabético. Para obtener más información, consulte Orden de los miembros de datos.

En el ejemplo siguiente, el contrato de datos para el tipo Employee es equivalente al contrato de datos para el tipo 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}.

Al pasar parámetros y devolver valores entre un cliente y un servicio, no se puede enviar un contrato de datos de una clase base cuando el punto de conexión receptor espera un contrato de datos de una clase derivada. Esto se ajusta a los principios de programación orientados a objetos. En el ejemplo anterior, no se puede enviar un objeto de tipo Person cuando se espera un Employee.

Se puede enviar un contrato de datos de una clase derivada cuando se espera un contrato de datos de una clase base, pero solo si el punto de conexión receptor "conoce" del tipo derivado mediante KnownTypeAttribute. Para obtener más información, vea Tipos conocidos del contrato de datos. En el ejemplo anterior, se puede enviar un objeto de tipo Employee cuando se espera un Person, pero solo si el código receptor emplea KnownTypeAttribute para incluirlo en la lista de tipos conocidos.

Al pasar parámetros y devolver valores entre aplicaciones, si el tipo esperado es una interfaz, equivale a que el tipo esperado sea de tipo Object. Dado que cada tipo deriva en última instancia de Object, cada contrato de datos deriva en última instancia del contrato de datos para Object. De este modo, se puede pasar cualquier tipo de contrato de datos cuando se espera una interfaz. Se requieren pasos adicionales para trabajar correctamente con interfaces; para obtener más información, vea Tipos conocidos del contrato de datos.

Consulte también