数据协定等效性
对于客户端要将某种类型的数据成功发送到服务,或者服务要将数据成功发送到客户端的情况,接收端上并不一定必须存在此发送数据类型。唯一的要求是两种类型的数据协定应该等效。(有时不要求严格等效,如数据协定版本管理中所述。)
要使数据协定等效,其命名空间和名称必须相同。此外,某一端上的每个数据成员还必须在另一端上具有等效的数据成员。
要使数据成员等效,其名称必须相同。此外,它们还必须表示同一类型的数据,也就是说,其数据协定必须等效。
注意: |
---|
请注意,数据协定名称和命名空间以及数据成员名称均区分大小写。 |
有关数据协定名称和命名空间以及数据成员名称的更多信息,请参见数据协定名称。
如果同一端(发送方或接收方)存在两种类型,而其数据协定又不等效(例如,它们的数据成员不同),则不应为它们指定相同的名称和命名空间。否则,可能会引发异常。
以下类型的数据协定是等效的:
<DataContract()> _
Public Class Customer
<DataMember()> _
Public fullName As String
<DataMember()> _
Public telephoneNumber As String
End Class
<DataContract(Name:="Customer")> _
Public Class Person
<DataMember(Name:="fullName")> _
Private nameOfPerson As String
Private address As String
<DataMember(Name:="telephoneNumber")> _
Private phoneNumber As String
End Class
[DataContract]
public class Customer
{
[DataMember]
public string fullName;
[DataMember]
public string telephoneNumber;
}
[DataContract(Name = "Customer")]
public class Person
{
[DataMember(Name = "fullName")]
private string nameOfPerson;
private string address;
[DataMember(Name = "telephoneNumber")]
private string phoneNumber;
}
数据成员顺序和数据协定等效性
使用 DataMemberAttribute 类的 Order 属性可能会影响数据协定等效性。其成员必须以相同顺序出现,数据协定才能等效。默认顺序是按字母顺序。有关更多信息,请参见 数据成员顺序.
例如,以下代码生成的数据协定是等效的。
<DataContract(Name := "Coordinates")> _
Public Class Coords1
<DataMember()> _
Public X As Integer
<DataMember()> _
Public Y As Integer
' Order is alphabetical (X,Y).
End Class
<DataContract(Name := "Coordinates")> _
Public Class Coords2
<DataMember()> _
Public Y As Integer
<DataMember()> _
Public X As Integer
' Order is alphabetical (X,Y), equivalent
' to the preceding code.
End Class
<DataContract(Name := "Coordinates")> _
Public Class Coords3
<DataMember(Order := 2)> _
Public Y As Integer
<DataMember(Order := 1)> _
Public X As Integer
' Order is according to the Order property (X,Y),
' equivalent to the preceding code.
End Class
[DataContract(Name = "Coordinates")]
public class Coords1
{
[DataMember]
public int X;
[DataMember]
public int Y;
// Order is alphabetical (X,Y).
}
[DataContract(Name = "Coordinates")]
public class Coords2
{
[DataMember]
public int Y;
[DataMember]
public int X;
// Order is alphabetical (X,Y), equivalent
// to the preceding code.
}
[DataContract(Name = "Coordinates")]
public class Coords3
{
[DataMember(Order = 2)]
public int Y;
[DataMember(Order = 1)]
public int X;
// Order is according to the Order property (X,Y),
// equivalent to the preceding code.
}
但是,以下代码生成的数据协定不是等效的。
<DataContract(Name := "Coordinates")> _
Public Class Coords4
<DataMember(Order := 1)> _
Public Y As Integer
<DataMember(Order := 2)> _
Public X As Integer
' Order is according to the Order property (Y,X),
' different from the preceding code.
End Class
[DataContract(Name = "Coordinates")]
public class Coords4
{
[DataMember(Order = 1)]
public int Y;
[DataMember(Order = 2)]
public int X;
// Order is according to the Order property (Y,X),
// different from the preceding code.
}
继承、接口和数据协定等效性
确定等效性时,对于从其他数据协定继承的数据协定,将被视为一个包含所有基类型的数据成员的数据协定。请记住,数据成员的顺序必须匹配,并且基类型成员排在派生类型成员之前。此外,如下面的代码示例所示,如果两个数据成员的顺序值相同,则这两个数据成员的顺序为按字母顺序。有关更多信息,请参见 数据成员顺序.
在下面的示例中,类型为 Employee
的数据协定等效于类型为 Worker
的数据协定。
<DataContract()> _
Public Class Person
<DataMember()> Public name As String
End Class
<DataContract()> _
Public Class Employee
Inherits Person
<DataMember()> Public department As Integer
<DataMember()> Public title As String
<DataMember()> Public salary As Integer
End class
' Order is "name", "department", "salary", "title"
' (base class first, then alphabetical).
<DataContract(Name:="Employee")> _
Public Class Worker
<DataMember(Order := 1)> _
Public name As String
<DataMember(Order := 2)> _
Public department As Integer
<DataMember(Order := 2)> _
Public title As String
<DataMember(Order := 2)> _
Public salary As Integer
End Class
' Order is "name", "department", "salary", "title"
' (Order=1 first, then Order=2 in alphabetical order),
' which is equivalent to the Employee order}.
[DataContract]
public class Person
{
[DataMember]
public string name;
}
[DataContract]
public class Employee : Person
{
[DataMember]
public int department;
[DataMember]
public string title;
[DataMember]
public int salary;
}
// Order is "name", "department", "salary", "title"
// (base class first, then alphabetical).
[DataContract(Name = "Employee")]
public class Worker
{
[DataMember(Order = 1)]
public string name;
[DataMember(Order = 2)]
public int department;
[DataMember(Order = 2)]
public string title;
[DataMember(Order = 2)]
public int salary;
}
// Order is "name", "department", "salary", "title"
// (Order=1 first, then Order=2 in alphabetical order),
// which is equivalent to the Employee order}.
在客户端和服务之间传递参数和返回值时,如果接收终结点要求来自派生类的数据协定,则不能发送来自基类的数据协定。这一点符合面向对象的编程原则。在前面的示例中,如果要求 Employee
,则不能发送 Person
类型的对象。
如果要求来自基类的数据协定,则可发送来自派生类的数据协定,但前提是接收终结点通过 KnownTypeAttribute“知道”该派生类型。有关更多信息,请参见 数据协定已知类型. 在前面的示例中,当要求 Person
时,可以发送 Employee
类型的对象,但前提是接收方代码使用 KnownTypeAttribute 将它包含在已知类型列表中。
在应用程序之间传递参数和返回值时,如果所需类型为接口,则等效于所需类型为 Object 类型。由于每种类型最终都派生自 Object,因此所有数据协定最终都派生自 Object 的数据协定。这样,在要求使用接口时,就可以传递任何数据协定类型。若要成功使用接口,还需要执行额外步骤;有关更多信息,请参见数据协定已知类型。
另请参见
参考
DataContractAttribute
DataMemberAttribute