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
- DataMemberAttribute
- DataContractAttribute
- Types sérialisables
- Noms de contrats de données
- Équivalence de contrats de données
- Classement des membres de données
- Types connus de contrats de données
- Contrats de données à compatibilité ascendante
- Contrôle de version des contrats de données
- Rappels de sérialisation avec tolérance de version
- Valeurs par défaut des membres de données
- Types pris en charge par le sérialiseur de contrat de données
- Procédure : créer un contrat de données de base pour une classe ou structure