Share via


Equivalência de Contrato de Dados

Para um cliente enviar com êxito dados de um determinado tipo para um serviço, ou um serviço para enviar dados com êxito para um cliente, o tipo enviado não precisa necessariamente existir na extremidade recetora. O único requisito é que os contratos de dados de ambos os tipos sejam equivalentes. (Por vezes, não é necessária uma equivalência estrita, como referido 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 dos dados sejam equivalentes, eles devem ter o mesmo nome. Além disso, devem representar o mesmo tipo de dados; ou seja, seus contratos de dados devem ser equivalentes.

Nota

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

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

Se existirem dois tipos no mesmo lado (remetente ou destinatário) e seus contratos de dados não forem equivalentes (por exemplo, eles tiverem membros de dados diferentes), você não deve dar a eles o mesmo nome e namespace. Isso pode fazer com que exceções sejam lançadas.

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 Pedido de Membro de Dados e Contrato de Dados

O uso da propriedade da classe pode afetar a OrderDataMemberAttribute 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, consulte Data Member Order.

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 que se segue não resulta num 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

Herança, interfaces e equivalência de contrato de dados

Ao determinar a equivalência, um contrato de dados que herda de outro contrato de dados é tratado como se fosse apenas um contrato de dados que inclui todos os membros de dados do tipo base. Lembre-se de que a ordem dos membros de dados deve corresponder e que os membros do tipo base precedem os membros do 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 ordem para esses membros de dados será alfabética. Para obter mais informações, consulte Data Member Order.

No exemplo a seguir, o contrato de dados para o tipo Employee é equivalente ao contrato de dados para o 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 de retorno 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 recetor espera um contrato de dados de uma classe derivada. Isso está de acordo com os princípios de programação orientada a objetos. 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 recetor "souber" do tipo derivado usando o KnownTypeAttribute. Para obter mais informações, consulte Tipos conhecidos de contrato de dados. No exemplo anterior, um objeto do tipo Employee pode ser enviado quando um Person é esperado, mas somente se o código do recetor empregar o KnownTypeAttribute para incluí-lo na lista de tipos conhecidos.

Ao passar parâmetros e valores de retorno entre aplicativos, se o tipo esperado for uma interface, é equivalente ao tipo esperado ser do tipo Object. Como cada tipo deriva, em última análise, do Object, cada contrato de dados deriva, em última análise, 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 sucesso com interfaces; para obter mais informações, consulte Tipos conhecidos de contrato de dados.

Consulte também