Usando contratos de dados
Um contrato de dados é um acordo formal entre um serviço e um cliente que descreve abstratamente os dados a serem trocados. Ou seja, para comunicar, o cliente e o serviço não precisam compartilhar os mesmos tipos, apenas os mesmos contratos de dados. Um contrato de dados define com precisão, para cada parâmetro ou tipo de retorno, quais dados são serializados (transformados em XML) a serem trocados.
Noções básicas sobre contratos de dados
O Windows Communication Foundation (WCF) usa um mecanismo de serialização chamado Data Contract Serializer por padrão para serializar e desserializar dados (convertê-los para e de XML). Todos os tipos primitivos do .NET Framework, como inteiros e cadeias de caracteres, bem como certos tipos tratados como primitivos, como DateTime e XmlElement, podem ser serializados sem outra preparação e são considerados como tendo contratos de dados padrão. Muitos tipos do .NET Framework também têm contratos de dados existentes. Para obter uma lista completa de tipos serializáveis, consulte Tipos suportados pelo Data Contract Serializer.
Novos tipos complexos criados devem ter um contrato de dados definido para que sejam serializáveis. Por padrão, o DataContractSerializer infere o contrato de dados e serializa todos os tipos publicamente visíveis. Todas as propriedades públicas de leitura/gravação e campos do tipo são serializados. Você pode excluir membros da serialização usando o IgnoreDataMemberAttribute. Você também pode criar explicitamente um contrato de dados usando DataContractAttribute e DataMemberAttribute atributos. Isso geralmente é feito aplicando o DataContractAttribute atributo ao tipo. Esse atributo pode ser aplicado a classes, estruturas e enumerações. O DataMemberAttribute atributo deve então ser aplicado a cada membro do tipo de contrato de dados para indicar que é um membro de dados, ou seja, deve ser serializado. Para obter mais informações, consulte Tipos serializáveis.
Exemplo
O exemplo a seguir mostra um contrato de serviço (uma interface) ao qual os ServiceContractAttribute atributos e OperationContractAttribute foram explicitamente aplicados. O exemplo mostra que os tipos primitivos não exigem um contrato de dados, enquanto um tipo complexo exige.
[ServiceContract]
public interface ISampleInterface
{
// No data contract is required since both the parameter
// and return types are primitive types.
[OperationContract]
double SquareRoot(int root);
// No Data Contract required because both parameter and return
// types are marked with the SerializableAttribute attribute.
[OperationContract]
System.Drawing.Bitmap GetPicture(System.Uri pictureUri);
// The MyTypes.PurchaseOrder is a complex type, and thus
// requires a data contract.
[OperationContract]
bool ApprovePurchaseOrder(MyTypes.PurchaseOrder po);
}
<ServiceContract()> _
Public Interface ISampleInterface
' No data contract is required since both the parameter and return
' types are both primitive types.
<OperationContract()> _
Function SquareRoot(ByVal root As Integer) As Double
' No Data Contract required because both parameter and return
' types are marked with the SerializableAttribute attribute.
<OperationContract()> _
Function GetPicture(ByVal pictureUri As System.Uri) As System.Drawing.Bitmap
' The MyTypes.PurchaseOrder is a complex type, and thus
' requires a data contract.
<OperationContract()> _
Function ApprovePurchaseOrder(ByVal po As MyTypes.PurchaseOrder) As Boolean
End Interface
O exemplo a seguir mostra como um contrato de dados para o MyTypes.PurchaseOrder
tipo é criado aplicando os DataContractAttribute atributos e DataMemberAttribute à classe e seus membros.
namespace MyTypes
{
[DataContract]
public class PurchaseOrder
{
private int poId_value;
// Apply the DataMemberAttribute to the property.
[DataMember]
public int PurchaseOrderId
{
get { return poId_value; }
set { poId_value = value; }
}
}
}
Namespace MyTypes
<System.Runtime.Serialization.DataContractAttribute()> _
Public Class PurchaseOrder
Private poId_value As Integer
' Apply the DataMemberAttribute to the property.
<DataMember()> _
Public Property PurchaseOrderId() As Integer
Get
Return poId_value
End Get
Set
poId_value = value
End Set
End Property
End Class
End Namespace
Notas
As notas a seguir fornecem itens a serem considerados ao criar contratos de dados:
O IgnoreDataMemberAttribute atributo só é honrado quando usado com tipos não marcados. Isso inclui tipos que não são marcados com um dos atributos , , , ou EnumMemberAttribute marcados DataContractAttributecomo serializáveis por qualquer outro meio (como IXmlSerializable). CollectionDataContractAttributeSerializableAttribute
Você pode aplicar o DataMemberAttribute atributo a campos e propriedades.
Os níveis de acessibilidade do membro (interno, privado, protegido ou público) não afetam o contrato de dados de forma alguma.
O DataMemberAttribute atributo será ignorado se for aplicado a membros estáticos.
Durante a serialização, o código property-get é chamado para que os membros de dados de propriedade obtenham o valor das propriedades a serem serializadas.
Durante a desserialização, um objeto não inicializado é criado primeiro, sem chamar nenhum construtor no tipo. Em seguida, todos os membros de dados são desserializados.
Durante a desserialização, o código do conjunto de propriedades é chamado para que os membros de dados de propriedade definam as propriedades para o valor que está sendo desserializado.
Para que um contrato de dados seja válido, deve ser possível serializar todos os seus membros de dados. Para obter uma lista completa de tipos serializáveis, consulte Tipos suportados pelo Data Contract Serializer.
Os tipos genéricos são tratados exatamente da mesma forma que os tipos não genéricos. Não existem requisitos especiais para parâmetros genéricos. Por exemplo, considere o seguinte tipo.
[DataContract]
public class MyGenericType1<T>
{
// Code not shown.
}
<DataContract()> _
Public Class MyGenericType1(Of T)
' Code not shown.
End Class
Esse tipo é serializável se o tipo usado para o parâmetro de tipo genérico (T
) é serializável ou não. Como deve ser possível serializar todos os membros de dados, o tipo a seguir é serializável somente se o parâmetro de tipo genérico também for serializável, conforme mostrado no código a seguir.
[DataContract]
public class MyGenericType2<T>
{
[DataMember]
T theData;
}
<DataContract()> _
Public Class MyGenericType2(Of T)
<DataMember()> _
Dim theData As T
End Class
Para obter um exemplo de código completo de um serviço WCF que define um contrato de dados, consulte o Exemplo de contrato de dados básico.
Consulte também
- DataMemberAttribute
- DataContractAttribute
- Tipos serializáveis
- Nomes de contratos de dados
- Equivalência de Contrato de Dados
- Pedido de Membro de Dados
- Tipos conhecidos de contrato de dados
- Contratos de dados compatíveis com o futuro
- Controle de versão de contrato de dados
- Retornos de chamada de serialização tolerantes à versão
- Valores padrão do membro de dados
- Tipos suportados pelo Data Contract Serializer
- Como: Criar um contrato de dados básicos para uma classe ou estrutura