Utilisation de contrats de données

Un contrat de données est un accord en bonne et due forme entre un service et un client qui décrit de manière abstraite les données à échanger. Autrement dit, pour communiquer, le client et le service n'ont pas besoin de partager les mêmes types, mais uniquement les mêmes contrats de données. Un contrat de données définit précisément, pour chaque type de paramètre ou de retour, les données qui doivent être sérialisées (converties en données XML) pour être échangées.

Principes de base des contrats de données

Windows Communication Foundation (WCF) utilise un moteur de sérialisation appelé par défaut Sérialiseur de contrat de données pour sérialiser et désérialiser des données (les convertir vers ou à partir de code XML). Tous les types primitifs .NET Framework, tels que les entiers et les chaînes, ainsi que certains types considérés comme primitifs, tels que DateTime et XmlElement, peuvent être sérialisés sans autre préparation et sont considérés comme ayant des contrats de données par défaut. De nombreux types .NET Framework ont également des contrats de données existants. Pour obtenir la liste complète des types sérialisables, consultez Types Supported by the Data Contract Serializer.

Vous devez définir un contrat de données pour les nouveaux types complexes que vous créez afin que ces derniers soient sérialisables. Par défaut, le DataContractSerializer déduit le contrat de données et sérialise tous les types visibles publiquement. Toutes les propriétés et tous les champs publics en lecture/écriture du type sont sérialisés. Vous pouvez supprimer des membres de la sérialisation en utilisant IgnoreDataMemberAttribute. Vous pouvez également créer explicitement un contrat de données à l'aide des attributs DataContractAttribute et DataMemberAttribute . Pour cela, il faut normalement appliquer l'attribut DataContractAttribute au type. Cet attribut peut être appliqué à des classes, des structures et des énumérations. Puis, l'attribut DataMemberAttribute doit être appliqué à chaque membre du type de contrat de données pour indiquer qu'il s'agit d'un membre de données, c'est-à-dire qu'il doit être sérialisé. Pour plus d’informations, consultez Types sérialisables.

Exemple

L'exemple suivant présente un contrat de service (une interface) auquel les attributs ServiceContractAttribute et OperationContractAttribute ont été explicitement appliqués. L'exemple montre que les types primitifs ne requièrent pas de contrat de données, contrairement au type complexe.

[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

L'exemple suivant montre comment créer un contrat de données pour le type MyTypes.PurchaseOrder en appliquant les attributs DataContractAttribute et DataMemberAttribute à la classe et à ses membres.

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

Notes

Les remarques suivantes fournissent des éléments à prendre en compte lors de la création de contrats de données :

  • L'attribut IgnoreDataMemberAttribute est honoré uniquement lorsqu'il est utilisé avec des types non marqués. Cela inclut les types qui ne sont pas marqués avec l'un des attributs DataContractAttribute, SerializableAttribute, CollectionDataContractAttributeou EnumMemberAttribute , ou qui sont marqués comme sérialisables par tout autre moyen (par exemple, objet IXmlSerializable).

  • Vous pouvez appliquer l'attribut DataMemberAttribute à des champs et à des propriétés.

  • Les niveaux d'accessibilité des membres (interne, privé, protégé ou public) n'affectent en aucune façon le contrat de données.

  • L'attribut DataMemberAttribute est ignoré s'il est appliqué à des membres statiques.

  • Pendant la sérialisation, le code de propriété get est appelé pour que les membres de données de propriété obtiennent la valeur des propriétés à sérialiser.

  • Pendant la désérialisation, un objet non initialisé est d'abord créé, sans appeler de constructeur sur le type. Puis, tous les membres de données sont désérialisés.

  • Pendant la désérialisation, le code de propriété set est appelé pour que les membres de données de propriété attribuent aux propriétés la valeur désérialisée.

  • Pour qu'un contrat de données soit valide, il doit être possible de sérialiser tous ses membres de données. Pour obtenir la liste complète des types sérialisables, consultez Types Supported by the Data Contract Serializer.

    Les types génériques sont gérés exactement de la même façon que les types non génériques. Les paramètres génériques n'ont pas d'exigences particulières. Considérons par exemple le type suivant.

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

Ce type est sérialisable, que le type utilisé pour le paramètre de type générique (T) le soit ou non. Comme il doit être possible de sérialiser tous les membres de données, le type suivant est sérialisable uniquement si le paramètre de type générique l'est également, tel qu'indiqué dans le code suivant.

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

Pour obtenir un exemple de code complet d’un service WCF qui définit un contrat de données, consultez l’exemple Basic Data Contract .

Voir aussi