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

Иногда клиент и служба поддерживают разные типы. Они все равно могут передавать данные друг другу при условии, что контракты данных эквивалентны на обеих сторонах. Эквивалентность контракта данных основана на именах контрактов данных и элементах данных, поэтому механизм предоставляется для сопоставления типов и элементов с этими именами. В этом разделе описываются правила именования контрактов данных, а также поведение инфраструктуры 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> имеет имя контракта данных "Drawing_using_RedBrush_brush_and_Square_shape". Обратите внимание, что так как в свойстве Name имеется знак "{#}", хэш не является частью имени, и, следовательно, могут возникнуть конфликты имен данного типа; например, тип Drawing<Square,SpecialRedBrush> имеет точно такое же имя контракта данных.

См. также