資料合約等價

若要讓用戶端成功地將特定型別的資料傳送至服務,或讓服務成功地將資料傳送至用戶端,傳送的型別不一定要存在於接收端。 唯一的需求是這兩個型別的資料合約必須相等 (有時候並不需要嚴格等價,如中的資料合約版本設定所述。)

若要讓資料合約相等,則資料合約必須具有相同的命名空間和名稱。 此外,某一端的每個資料成員都必須有另一端的對等資料成員。

若要讓資料成員相等,則資料成員必須具有相同的名稱。 此外,還必須有相同的資料型別,也就是說,它們的資料合約必須相等。

注意

請注意,資料合約名稱、命名空間和資料成員名稱必須區分大小寫。

如需資料合約名稱和命名空間以及資料成員名稱的詳細資訊,請參閱資料合約名稱

如果兩個型別存在於同一端 (傳送者或接收者),但資料合約不相等 (例如,具有不同的資料成員),則不應該為它們指定相同的名稱和命名空間。 這樣做可能會導致擲回例外狀況。

下列型別的資料合約是相等的:

[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;
}
<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

資料成員順序和資料合約等價

使用 Order 類別的 DataMemberAttribute 屬性,可能會影響資料合約等價。 資料合約必須以相同順序顯示成員,才會相等。 預設順序是字母順序。 如需詳細資訊,請參閱資料成員順序

例如,下列程式碼會產生對等的資料合約。

[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 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 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.
}
<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

繼承、介面和資料合約等價

判斷等價時,繼承自另一個資料合約的資料合約會被視為只是一個包含所有來自基底型別之資料成員的資料合約。 請記住,資料成員的順序必須相符,而且基底型別成員的順序必須在衍生型別成員之前。 此外,如果兩個資料成員有相同的順序值,則這些資料成員的順序為字母順序 (如下列程式碼範例)。 如需詳細資訊,請參閱資料成員順序

在下列範例中,Employee 型別的資料合約與 Worker 型別的資料合約相等。

[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}.
<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}.

在用戶端和服務之間傳遞參數和傳回值時,如果接收端點需要來自衍生類別的資料合約,則無法傳送來自基底類別的資料合約。 這符合物件導向程式設計原則。 在上一個範例中,需要Employee時,則無法傳送Person型別的物件。

如果需要來自基底類別的資料合約,只有在接收端點使用 KnownTypeAttribute 知道衍生型別時,才能傳送來自衍生類別的資料合約。 如需資料合約已知型別的詳細資訊,請參閱資料合約型別。 在上一個範例中,如果需要 Employee,只有在接收者程式碼使用 PersonKnownTypeAttribute 型別的物件包含在已知型別的清單時,才能傳送它。

在應用程式之間傳遞參數和傳回值時,如果預期型別是介面,它相當於 Object 型別的預期型別。 因為每個型別最終都是衍生自 Object,所以每個資料合約最終都會衍生自 Object 的資料合約。 因此,如果需要介面,則可以傳遞任何資料合約類型。 如果要成功使用介面,還需要執行其他額外步驟。如需詳細資訊,請參閱資料合約型別

另請參閱