Partager via


Noms de contrats de données

Il arrive parfois qu'un client et un service ne partagent pas les mêmes types. Ils peuvent toujours se transmettre des données tant que les contrats de données sont équivalents des deux côtés. L’équivalence des contrats de données est basée sur les noms des contrats de données et des membres de données. Un mécanisme est donc fourni pour mapper des types et des membres à ces noms. Cette rubrique explique les règles de nommage des contrats de données ainsi que le comportement par défaut de l’infrastructure Windows Communication Foundation (WCF) lors de la création de noms.

Règles de base

Les règles de base concernant l'attribution de noms aux contrats de données sont les suivantes :

  • Un nom de contrat de données complet se compose d'un espace de noms et d'un nom.

  • Les membres de données incluent uniquement des noms, mais pas d'espace de noms.

  • Lors du traitement des contrats de données, l’infrastructure WCF respecte aussi bien la casse des espaces de noms que celle des noms de contrats de données et de membres de données.

Espaces de noms de contrat de données

Un espace de noms de contrat de données prend la forme d'un URI (Uniform Resource Identifier). L'URI peut être absolu ou relatif. Par défaut, les contrats de données d'un type spécifique sont affectés d'un espace de noms provenant de l'espace de noms CLR (Common Language Runtime) de ce type.

Par défaut, tout espace de noms CLR donné (au format Clr.Namespace) est mappé à l’espace de noms http://schemas.datacontract.org/2004/07/Clr.Namespace. Pour substituer cette valeur par défaut, appliquez l'attribut ContractNamespaceAttribute à l'ensemble du module ou de l'assembly. Ou bien, pour contrôler l'espace de noms de contrat de données pour chaque type, définissez la propriété Namespace de DataContractAttribute.

Notes

L’espace de noms http://schemas.microsoft.com/2003/10/Serialization est réservé et ne peut pas être utilisé comme espace de noms de contrat de données.

Notes

Vous ne pouvez pas substituer l'espace de noms par défaut dans les types de contrats de données contenant des déclarations delegate.

Noms de contrats de données

Le nom par défaut d'un contrat de données d'un type donné correspond au nom de ce type. Pour substituer la valeur par défaut, affectez un autre nom à la propriété Name de DataContractAttribute. Les règles spéciales pour les types génériques sont décrites dans « Noms de contrat de données pour les types génériques », un peu plus loin dans cette rubrique.

Noms de membre de données

Le nom par défaut d'un membre de données pour une propriété ou un champ donné correspond au nom de cette propriété ou de ce champ. Pour substituer la valeur par défaut, affectez une autre valeur à la propriété Name de DataMemberAttribute.

Exemples

L'exemple suivant indique comment vous pouvez substituer le comportement d'attribution de noms par défaut des contrats de données et des membres de données.

// This overrides the standard namespace mapping for all contracts
// in Contoso.CRM.
[assembly: ContractNamespace("http://schemas.example.com/crm",
   ClrNamespace = "Contoso.CRM")]
namespace Contoso.CRM
{
    // The namespace is overridden to become:
    // http://schemas.example.com/crm.
    // But the name is the default "Customer".
    [DataContract]
    public class Customer
    {
        // Code not shown.
    }
}
namespace Contoso.OrderProc
{
    [DataContract]
    public class PurchaseOrder
    {
        // This data member is named "Amount" by default.
        [DataMember]
        public double Amount;

        // The default is overridden to become "Address".
        [DataMember(Name = "Address")]
        public string Ship_to;
    }
    // The namespace is the default value:
    // http://schemas.datacontract.org/2004/07/Contoso.OrderProc
    // The name is "PurchaseOrder" instead of "MyInvoice".
    [DataContract(Name = "PurchaseOrder")]
    public class MyInvoice
    {
        // Code not shown.
    }

    // The contract name is "Payment" instead of "MyPayment"
    // and the Namespace is "http://schemas.example.com" instead
    // of the default.
    [DataContract(Name = "Payment",
        Namespace = "http://schemas.example.com")]
    public class MyPayment
    {
        // Code not shown.
    }
}
' This overrides the standard namespace mapping for all contracts 
' in Contoso.CRM. 
<Assembly: ContractNamespace("http://schemas.example.com/crm", _
ClrNamespace:="Contoso.CRM")>
Namespace Contoso.CRM
    ' The namespace is overridden to become: 
    ' http://schemas.example.com/crm.
    ' But the name is the default "Customer".
    <DataContract()> _
    Public Class Customer
        ' Code not shown.
    End Class
End Namespace

Namespace Contoso.OrderProc
    <DataContract()> _
    Public Class PurchaseOrder
        ' This data member is named "Amount" by default.
        <DataMember()> _
        Public Amount As Double

        ' The default is overridden to become "Address".
        <DataMember(Name:="Address")> _
        Public Ship_to As String
    End Class

    ' The namespace is the default value:
    ' http://schemas.datacontract.org/2004/07/Contoso.OrderProc
    ' The name is "PurchaseOrder" instead of "MyInvoice".
    <DataContract(Name:="PurchaseOrder")> _
    Public Class MyInvoice
        ' Code not shown.
    End Class

    ' The contract name is "Payment" instead of "MyPayment" 
    ' and the Namespace is "http://schemas.example.com" instead
    ' of the default.
    <DataContract(Name:="Payment", [Namespace]:="http://schemas.example.com")> _
    Public Class MyPayment
        ' Code not shown.
    End Class
End Namespace

Noms de contrat de données pour les types génériques

Il existe des règles spéciales pour déterminer des noms de contrat de données pour les types génériques. Elles permettent d'éviter les conflits de noms de contrat de données entre deux génériques fermés du même type générique.

Par défaut, le nom de contrat de données pour un type générique correspond au nom du type, suivi de la chaîne « Of », suivie des noms de contrat de données des paramètres génériques, suivis d’un hachage calculé à l’aide des espaces de noms de contrat de données des paramètres génériques. Un hachage est le résultat d'une fonction mathématique qui agit comme une « empreinte digitale » et identifie de manière unique une portion de données. Lorsque tous les paramètres génériques sont des types primitifs, le hachage est omis.

Par exemple, considérez les types illustrés dans l'exemple suivant.

[DataContract]
public class Drawing<Shape, Brush>
{
    // Code not shown.
}

[DataContract(Namespace = "urn:shapes")]
public class Square
{
    // Code not shown.
}

[DataContract(Name = "RedBrush", Namespace = "urn:default")]
public class RegularRedBrush
{
    // Code not shown.
}

[DataContract(Name = "RedBrush", Namespace = "urn:special")]
public class SpecialRedBrush
{
    // Code not shown.
}
<DataContract()> _
Public Class Drawing(Of Shape, Brush)

    <DataContract([Namespace]:="urn:shapes")> _
    Public Class Square
        ' Code not shown.
    End Class


    <DataContract(Name:="RedBrush", [Namespace]:="urn:default")> _
    Public Class RegularRedBrush
        ' Code not shown.
    End Class

    <DataContract(Name:="RedBrush", [Namespace]:="urn:special")> _
    Public Class SpecialRedBrush
        ' Code not shown.
    End Class
End Class

Dans cet exemple, le type Drawing<Square,RegularRedBrush> a le nom de contrat de données "DrawingOfSquareRedBrush5HWGAU6h", où "5HWGAU6h" est un hachage des espaces de noms "urn:shapes" et "urn:default". Le type Drawing<Square,SpecialRedBrush> a le nom de contrat de données "DrawingOfSquareRedBrushjpB5LgQ_S", où "jpB5LgQ_S" est un hachage des espaces de noms "urn:shapes" et "urn:special". Notez que si le hachage n'est pas utilisé, les deux noms sont identiques, et donc une collision de nom se produit.

Personnalisation des noms de contrat de données pour les types génériques

Il arrive parfois que les noms de contrat de données générés pour les types génériques, comme décrit précédemment, soient inacceptables. Par exemple, peut-être savez-vous déjà qu'il n'y aura pas de conflit de noms et souhaitez supprimer le hachage. Dans ce cas, vous pouvez utiliser la propriété DataContractAttribute.Name pour spécifier une autre méthode de génération de noms. Vous pouvez utiliser des nombres dans les accolades à l'intérieur de la propriété Name pour faire référence aux noms de contrat de données des paramètres génériques. (0 fait référence au premier paramètre, 1 au deuxième, etc.) Vous pouvez utiliser un signe dièse (#) entre accolades pour faire référence au hachage. Vous pouvez utiliser chacune de ces références à plusieurs reprises ou ne pas les utiliser du tout.

Par exemple, le type Drawing générique précédent aurait pu être déclaré comme indiqué dans l'exemple suivant.

[DataContract(Name = "Drawing_using_{1}_brush_and_{0}_shape")]
public class Drawing<Shape, Brush>
{
    // Code not shown.
}
<DataContract(Name:="Drawing_using_{1}_brush_and_{0}_shape")> _
Public Class Drawing(Of Shape, Brush)
    ' Code not shown.
End Class

Dans ce cas, le type Drawing<Square,RegularRedBrush> a le nom de contrat de données "Drawing_using_RedBrush_brush_and_Square_shape". Notez que du fait de la présence de "{#}" dans la propriété Name, le hachage n'est pas une partie du nom, et que par conséquent, le type peut être exposé à des conflits de noms ; par exemple, le type Drawing<Square,SpecialRedBrush> aurait exactement le même nom de contrat de données.

Voir aussi