Compartir a través de


Utilización de contratos de datos

Un contrato de datos es un acuerdo formal entre un servicio y un cliente que abstractamente describe 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 (se convierten en XML) para su intercambio.

Fundamentos del contrato de datos

Windows Communication Foundation (WCF) utiliza un motor de la serialización llamado Serializador de contrato de datos de forma predeterminada para serializar y deserializar los datos (convertirlos de y a XML). Todos los tipos primitivos .NET Framework, como enteros y cadenas, así como ciertos tipos tratados como primitivos, como DateTime y XmlElement, se pueden serializar sin otra preparación y se considera que tienen contratos de datos predeterminados. Muchos tipos .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 se crean deben tener un contrato de datos definido para que sean serializables. De forma predeterminada, DataContractSerializer deduce el contrato de datos y serializa todos los tipos públicamente visibles. Se serializan todos los campos y propiedades de lectura y escritura públicos del tipo. Puede descartar miembros de la serialización mediante el uso de IgnoreDataMemberAttribute. También puede crear explícitamente un contrato de datos mediante el uso de los atributos DataMemberAttribute y DataContractAttribute. Esto se hace normalmente aplicando el atributo DataContractAttribute al tipo. Este atributo se puede aplicar a clases, estructuras y enumeraciones. El atributo DataMemberAttribute se debe aplicar a continuación a cada miembro del tipo de contrato de datos para indicar que es un miembro de datos, es decir, que se debería serializar. 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 los atributos ServiceContractAttribute y OperationContractAttribute explícitamente. El ejemplo muestra que los tipos primitivos no requieren un contrato de datos, mientras un tipo complejo sí lo hace.

<ServiceContract()>  _
Public Interface ISampleInterface
    ' No data contract is requred 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 
[ServiceContract]
public interface ISampleInterface
{
    // No data contract is requred 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);
}

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

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 
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; }
        }
    }
}

Notas

Las notas siguientes proporcionan los elementos a considerar al crear los contratos de datos:

  • El atributo IgnoreDataMemberAttribute se observa solo cuando se usa con tipos no marcados. Se incluyen los tipos que no están marcados con uno de los atributos DataContractAttribute, SerializableAttribute, EnumMemberAttribute o CollectionDataContractAttribute, o que están marcados como serializables de alguna otra forma (como IXmlSerializable).

  • Puede aplicar el atributo DataMemberAttribute a campos y propiedades.

  • Los niveles (interno, privado, protegido o público) de accesibilidad de miembros no afectan de forma alguna al contrato de datos.

  • Se omite el atributo DataMemberAttribute si se aplica a los 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 no inicializado, 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 de datos. Para obtener una lista completa de los tipos serializables, vea Tipos admitidos por el serializador de contrato de datos.

    Los tipos genéricos se administran exactamente de la misma manera como los tipos no genéricos. No hay ningún requisito especial para los parámetros genéricos. Por ejemplo, veamos el siguiente tipo.

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

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

<DataContract()> Public Class MyGenericType2(Of T)

    <DataMember()> Dim theData As T

End Class 
[DataContract]
public class MyGenericType2<T>
{
    [DataMember]
    T theData;
}

Vea también

Tareas

Cómo: Crear un contrato de datos básicos para una clase o estructura

Referencia

DataMemberAttribute
DataContractAttribute

Conceptos

Tipos serializables
Nombres de contratos de datos
Equivalencia del contrato de datos
Orden de los miembros de datos
Tipos conocidos de contratos de datos
Contratos de datos compatibles con el reenvío
Versiones de contratos de datos
Devoluciones de llamadas en la serialización tolerante a versiones
Valores predeterminados de los miembros de datos
Tipos admitidos por el serializador de contrato de datos