有时,客户端和服务不共享相同的类型。 只要数据协定在双方等效,它们仍然可以相互传递数据。 数据协定等效 性基于数据协定和数据成员名称,因此提供了一种机制,用于将类型和成员映射到这些名称。 本主题介绍在创建名称时命名数据协定的规则以及 Windows Communication Foundation (WCF) 基础结构的默认行为。
基本规则
有关命名数据协定的基本规则包括:
完全限定的数据协定名称由命名空间和名称组成。
数据成员只有名称,但没有命名空间。
处理数据协定时,WCF 基础结构对数据协定和数据成员的命名空间和名称区分大小写。
数据协定命名空间
数据协定命名空间采用统一资源标识符(URI)的形式。 URI 可以是绝对 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>
会有完全相同的数据契约名称。