Equivalência de contrato de dados

Para um cliente enviar com êxito dados de um determinado tipo para um serviço ou para um serviço para enviar dados com êxito a um cliente, o tipo enviado não precisa necessariamente existir na extremidade de recebimento. O único requisito é que os contratos de dados de ambos os tipos sejam equivalentes. (Às vezes, a equivalência estrita não é necessária, conforme discutido em Controle de versão do contrato de dados.)

Para que os contratos de dados sejam equivalentes, eles devem ter o mesmo namespace e nome. Além disso, cada membro de dados de um lado deve ter um membro de dados equivalente do outro lado.

Para que os membros de dados sejam equivalentes, eles devem ter o mesmo nome. Além disso, eles devem representar o mesmo tipo de dados; ou seja, seus contratos de dados devem ser equivalentes.

Observação

Observe que nomes e namespaces de contrato de dados, bem como os nomes de membros de dados, diferenciam maiúsculas de minúsculas.

Para obter mais informações sobre nomes e namespaces de contrato de dados, bem como sobre nomes de membros de dados, consulte Nomes de contrato de dados.

Se dois tipos existirem no mesmo lado (remetente ou receptor) e seus contratos de dados não forem equivalentes (por exemplo, eles têm membros de dados diferentes), você não deve dar a eles o mesmo nome e namespace. Fazer isso pode causar o lançamento de exceções.

Os contratos de dados para os seguintes tipos são 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

Equivalência de contrato de dados e ordem de membro de dados

O uso da propriedade Order da classe DataMemberAttribute pode afetar a equivalência do contrato de dados. Os contratos de dados devem ter membros que aparecem na mesma ordem para serem equivalentes. A ordem padrão é alfabética. Para obter mais informações, confira Ordem do membro de dados.

Por exemplo, o código a seguir resulta em contratos de dados 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

No entanto, o seguinte não resulta em um contrato de dados 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

Equivalência do contrato de dados, herança e interfaces

Ao determinar a equivalência, um contrato de dados herdado de outro contrato de dados é tratado como se fosse apenas um contrato de dados que inclui todos os membros de dados do tipo base. Tenha em mente que a ordem dos membros de dados deve corresponder e que os membros do tipo base precedem membros de tipo derivado na ordem. Além disso, se, como no exemplo de código a seguir, dois membros de dados tiverem o mesmo valor de ordem, a ordenação para esses membros de dados será alfabética. Para obter mais informações, confira Ordem do membro de dados.

No exemplo a seguir, o contrato de dados para tipo Employee é equivalente ao contrato de dados do 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}.

Ao passar parâmetros e valores retornados entre um cliente e um serviço, um contrato de dados de uma classe base não pode ser enviado quando o ponto de extremidade receptor espera um contrato de dados de uma classe derivada. Isso está de acordo com os princípios de programação orientados a objeto. No exemplo anterior, um objeto do tipo Person não pode ser enviado quando um Employee é esperado.

Um contrato de dados de uma classe derivada pode ser enviado quando um contrato de dados de uma classe base é esperado, mas somente se o ponto de extremidade receptor "souber" do tipo derivado usando o KnownTypeAttribute. Para saber mais, confira Tipos de contrato de dados conhecidos. No exemplo anterior, um objeto do tipo Employee pode ser enviado quando um Person é esperado, mas somente se o código receptor empregar o KnownTypeAttribute para incluí-lo na lista de tipos conhecidos.

Ao passar parâmetros e retornar valores entre aplicativos, se o tipo esperado for uma interface, ele será equivalente ao tipo esperado sendo do tipo Object. Como cada tipo, em última análise, deriva de Object, cada contrato de dados, em última análise, deriva do contrato de dados para Object. Assim, qualquer tipo de contrato de dados pode ser passado quando uma interface é esperada. Etapas adicionais são necessárias para trabalhar com êxito com interfaces. Para obter mais informações, consulte Tipos conhecidos de contrato de dados.

Confira também