データ コントラクトの等価性
クライアントがサービスに特定の型のデータを正常に送信するために、またはサービスがクライアントにデータを正常に送信するために、送信する型が受信側に存在する必要があるとは限りません。 両方の型のデータ コントラクトが同等であるということが唯一の要件です (「データ コントラクトのバージョン管理」で説明されているように、厳密な等価性は必要ではないことがあります)
データ コントラクトを同等にするには、そのデータ コントラクトに同じ名前空間と名前を使用する必要があります。 また、一方のデータ コントラクトの各データ メンバーには、他方のデータ コントラクトに同等のデータ メンバーがある必要があります。
データ メンバーを同等にするには、そのデータ メンバーに同じ名前を使用する必要があります。 さらに、データ メンバーは同じ型のデータを表す必要があります。つまり、データ コントラクトが同等である必要があります。
Note
データ コントラクト名と名前空間、およびデータ メンバー名は、大文字と小文字を区別します。
データ コントラクトの名前と名前空間、ならびにデータ メンバーの名前に関する詳細については、「データ コントラクト名」を参照してください。
2 つの型が両側 (送信者と受信者) に存在し、そのデータ コントラクトが同等でない場合 (たとえば、異なるデータ メンバーを含んでいる場合)、そのデータ コントラクトに同じ名前と名前空間を使用しないでください。 同じ名前と名前空間を使用すると、例外がスローされる可能性があります。
次の型のデータ コントラクトは同等です。
[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
継承、インターフェイス、およびデータ コントラクトの等価性
等価性を判断するとき、別のデータ コントラクトから継承したデータ コントラクトは、基本型のすべてのデータ メンバーを含んでいる 1 つのデータ コントラクトとして扱われます。 データ メンバーの順序が一致する必要があり、基本型のメンバーは派生型のメンバーより前に現れる必要があります。 さらに、次のコード例のように、2 つのデータ メンバーの順序の値が同じ場合、そのデータ メンバーの順序はアルファベット順になります。 詳細については、「データ メンバーの順序」を参照してください。
次の例では、型 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
が予期されるときに、受信者のコードが既知の型のリストに Person
を追加するために KnownTypeAttribute を使用している場合のみ、型 Employee のオブジェクトを送信できます。
アプリケーション間でパラメーターを渡し、値を返すとき、予期される型がインターフェイスの場合、その型は、型が Object の予期される型と同等です。 すべての型は最終的に Object から派生するので、すべてのデータ コントラクトは最終的に、Object のデータ コントラクトから派生します。 したがって、インターフェイスが予期されるとき、すべてのデータ コントラクト型を渡すことができます。 インターフェイスを正常に操作するには追加の手順が必要です。詳細については、「既知のデータ コントラクト型」を参照してください。