Compartir a través de


Uso de contratos de datos

Un contrato de datos es un acuerdo formal entre un servicio y un cliente que describe abstractamente los datos que se van a intercambiar. Es decir, para comunicarse, el cliente y el servicio no tienen que compartir los mismos tipos, solo los mismos contratos de datos. Un contrato de datos define con precisión, para cada parámetro o tipo de valor devuelto, qué datos se serializan (convertidos en XML) que se van a intercambiar.

Conceptos básicos del contrato de datos

Windows Communication Foundation (WCF) usa un motor de serialización denominado Serializador de contrato de datos de forma predeterminada para serializar y deserializar datos (convertirlos a y desde XML). Todos los tipos primitivos de .NET Framework, como enteros y cadenas, así como ciertos tipos tratados como primitivos, como DateTime y XmlElement, se pueden serializar sin ninguna otra preparación y se consideran que tienen contratos de datos predeterminados. Muchos tipos de .NET Framework también tienen contratos de datos existentes. Para obtener una lista completa de los tipos serializables, vea Tipos admitidos por el serializador de contrato de datos.

Los nuevos tipos complejos que cree deben tener definido un contrato de datos para que sean serializables. De forma predeterminada, DataContractSerializer deduce el contrato de datos y serializa todos los tipos visibles públicamente. Todas las propiedades y campos de lectura y escritura públicos del tipo se serializan. Puede descartar miembros de la serialización mediante el uso de IgnoreDataMemberAttribute. También puede crear explícitamente un contrato de datos mediante los atributos DataContractAttribute y DataMemberAttribute. Normalmente, esto se hace aplicando el DataContractAttribute atributo al tipo . Este atributo se puede aplicar a clases, estructuras y enumeraciones. A continuación, el atributo debe aplicarse a cada miembro del tipo de contrato de datos para indicar que es un DataMemberAttribute, es decir, debe serializarse. Para obtener más información, vea Tipos serializables.

Ejemplo

En el ejemplo siguiente se muestra un contrato de servicio (una interfaz) al que se han aplicado explícitamente los ServiceContractAttribute atributos y OperationContractAttribute . En el ejemplo se muestra que los tipos primitivos no requieren un contrato de datos, mientras que un tipo complejo sí.

[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

En el ejemplo siguiente se muestra cómo se crea un contrato de datos para el MyTypes.PurchaseOrder tipo aplicando los DataContractAttribute atributos y DataMemberAttribute a la clase y sus miembros.

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

En las notas siguientes se proporcionan elementos que se deben tener en cuenta al crear contratos de datos:

  • El IgnoreDataMemberAttribute atributo solo se respeta cuando se usa con tipos sin marcar. Esto incluye tipos que no están marcados con uno de los DataContractAttributeatributos , SerializableAttribute, CollectionDataContractAttributeo EnumMemberAttribute , o marcados como serializables por cualquier otro medio (como IXmlSerializable).

  • Puede aplicar el DataMemberAttribute atributo a campos y propiedades.

  • Los niveles de accesibilidad de los miembros (internos, privados, protegidos o públicos) no afectan al contrato de datos de ninguna manera.

  • El DataMemberAttribute atributo se omite si se aplica a miembros estáticos.

  • Durante la serialización, se llama al código de obtención de propiedades para que los miembros de datos de propiedad obtengan el valor de las propiedades a serializar.

  • Durante la deserialización, primero se crea un objeto sin inicializar, sin llamar a ningún constructor en el tipo. A continuación, se deserializan todos los miembros de datos.

  • Durante la serialización, se llama al código de conjunto de propiedades para que los miembros de datos de propiedad establezcan el valor de las propiedades que se están deserializando.

  • Para que un contrato de datos sea válido, debe ser posible serializar todos sus miembros del contrato. Para obtener una lista completa de los tipos serializables, vea Tipos admitidos por el serializador de contrato de datos.

    Los tipos genéricos se controlan exactamente de la misma manera que los tipos no genéricos. No hay requisitos especiales para los parámetros genéricos. Por ejemplo, considere el siguiente tipo.

[DataContract]
public class MyGenericType1<T>
{
    // Code not shown.
}
<DataContract()> _
Public Class MyGenericType1(Of T)
    ' Code not shown.
End Class

Este tipo es serializable si el tipo usado para el parámetro de tipo genérico (T) es serializable o no. Dado que debe ser posible serializar todos los miembros de datos, el siguiente tipo solo se puede serializar si el parámetro de tipo genérico también es serializable, como se muestra en el código siguiente.

[DataContract]
public class MyGenericType2<T>
{
    [DataMember]
    T theData;
}
<DataContract()> _
Public Class MyGenericType2(Of T)
    <DataMember()> _
    Dim theData As T
End Class

Para obtener un ejemplo de código completo de un servicio WCF que define un contrato de datos, consulte el ejemplo de contrato de datos básico .

Consulte también