Имена данных контрактов

Иногда клиент и услуга не делятся одинаковыми типами. Они по-прежнему могут передавать данные друг другу, если контракты на данные эквивалентны обеим сторонам. Эквивалентность контракта данных основана на именах контрактов данных и элементах данных, поэтому механизм предоставляется для сопоставления типов и элементов с этими именами. В этом разделе описываются правила именования контрактов данных, а также поведение инфраструктуры Windows Communication Foundation (WCF) по умолчанию при создании имен.

Основные правила

Ниже указаны основные правила, касающиеся контрактов именования данных:

  • Полное имя контракта данных состоит из пространства имен и имени.

  • Члены данных имеют только имена, но не имеют пространств имен.

  • При обработке контрактов данных инфраструктура WCF учитывает регистр как пространства имен, так и имена контрактов данных и членов данных.

Пространства имен контракта данных

Пространство имен контракта данных имеет форму универсального идентификатора ресурса (URI). Универсальный код ресурса (URI) может быть абсолютным или относительным. По умолчанию контракты данных для определенного типа назначаются пространству имен, которое поступает из пространства имен общего языка выполнения (CLR) для этого типа.

По умолчанию любое заданное пространство имен CLR (в формате Clr.Namespace) сопоставляется с пространством http://schemas.datacontract.org/2004/07/Clr.Namespaceимен. Чтобы переопределить этот параметр по умолчанию, примените ContractNamespaceAttribute атрибут ко всему модулю или сборке. Кроме того, чтобы управлять пространством имен контракта данных для каждого типа, задайте Namespace свойство объекта DataContractAttribute.

Замечание

Пространство http://schemas.microsoft.com/2003/10/Serialization имен зарезервировано, и не может использоваться в качестве пространства имен для контракта данных.

Замечание

Нельзя переопределить пространство имен по умолчанию в типах контрактов данных, содержащих delegate декларации.

Имена данных контрактов

Имя контракта данных по умолчанию для заданного типа — это имя этого типа. Чтобы переопределить значение по умолчанию, задайте свойству Name объекта DataContractAttribute альтернативное имя. Специальные правила для универсальных типов описаны в разделе "Имена контрактов данных для универсальных типов" далее в этом разделе.

Имена элементов данных

Имя элемента данных по умолчанию для заданного поля или свойства — это имя этого поля или свойства. Чтобы переопределить значение по умолчанию, задайте свойству Name объекта DataMemberAttribute альтернативное значение.

Примеры

В следующем примере показано, как можно переопределить поведение именования по умолчанию контрактов данных и членов данных.

// 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

Имена соглашений о данных для универсальных типов

Специальные правила существуют для определения имен контрактов данных для универсальных типов. Эти правила помогают избежать конфликтов названий контракта данных между двумя закрытыми экземплярами одного и того же универсального типа.

По умолчанию имя контракта данных для универсального типа состоит из имени типа, затем строки "Of", далее имен контрактов данных универсальных параметров и хэша, вычисленного на основе пространств имен контрактов данных универсальных параметров. Хэш является результатом математической функции, которая выступает в качестве "отпечатка пальца", который однозначно идентифицирует часть данных. Если все универсальные параметры являются примитивными типами, хэш опущен.

Например, см. типы в следующем примере.

[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

В этом примере тип Drawing<Square,RegularRedBrush> имеет имя контракта данных "DrawingOfSquareRedBrush5HWGAU6h", где "5HWGAU6h" представляет собой хэш пространств имен "urn:shapes" и "urn:default". Тип Drawing<Square,SpecialRedBrush> имеет имя контракта данных "DrawingOfSquareRedBrushjpB5LgQ_S", где "jpB5LgQ_S" является хэшом пространств имен "urn:shapes" и "urn:special". Обратите внимание, что если хэш не используется, эти два имени идентичны, поэтому возникает столкновение имен.

Настройка имен контрактов данных для обобщенных типов

Иногда названия контрактов данных, которые создаются для универсальных типов, как было описано ранее, могут быть неприемлемы. Например, вы можете заранее знать, что не будете сталкиваться с конфликтами имен и захотите удалить хэш. В этом случае вы можете использовать свойство DataContractAttribute.Name, чтобы указать другой способ создания имён. Вы можете использовать числа в фигурных скобках внутри свойства Name, чтобы ссылаться на названия контрактов данных универсальных параметров. (0 относится к первому параметру, 1 ссылается на второй и т. д.) Для ссылки на хэш можно использовать знак (#) внутри фигурных скобок. Вы можете использовать каждую из этих ссылок несколько раз или вообще не использовать.

Например, предыдущий универсальный Drawing тип может быть объявлен, как показано в следующем примере.

[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

В этом случае тип Drawing<Square,RegularRedBrush> имеет имя контракта данных "Рисование_с_использованием_кисти_Красного_Цвета_и_формы_Квадрат". Обратите внимание, что поскольку в Name свойстве есть "{#}", хэш не является частью имени, поэтому тип подвержен конфликтам именования; например, тип Drawing<Square,SpecialRedBrush> будет иметь точно то же имя контракта данных.

См. также