クライアントが特定の種類のデータをサービスに正常に送信したり、サービスからクライアントにデータを正常に送信したりするには、送信された型が受信側に必ずしも存在する必要はありません。 唯一の要件は、両方の型のデータ コントラクトが同等であるということです。 (場合によっては、「 データ コントラクトのバージョン管理」で説明されているように、厳密な等価性は必要ありません)。
データ コントラクトを同等にするには、同じ名前空間と名前を持つ必要があります。 さらに、一方の側の各データ メンバーには、もう一方の側に同等のデータ メンバーが必要です。
データ メンバーを同等にするには、同じ名前を持つ必要があります。 さらに、同じ種類のデータを表す必要があります。つまり、データ コントラクトは同等である必要があります。
注
データ コントラクト名と名前空間、およびデータ メンバー名は、大文字と小文字を区別します。
データ コントラクト名と名前空間、およびデータ メンバー名の詳細については、「 データ コントラクト名」を参照してください。
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}.
クライアントとサービスの間でパラメーターを渡して値を返す場合、受信側のエンドポイントが派生クラスからのデータ コントラクトを想定している場合、基底クラスからのデータ コントラクトを送信できません。 これは、オブジェクト指向プログラミングの教義に従います。 前の例では、Person
が必要な場合、Employee
型のオブジェクトを送信できません。
派生クラスからのデータ コントラクトは、基底クラスからのデータ コントラクトが必要な場合に送信できますが、受信エンドポイントが KnownTypeAttributeを使用して派生型を "認識" している場合にのみ送信できます。 詳細については、「 データ コントラクトの既知の型」を参照してください。 前の例では、 Employee
型のオブジェクトは、 Person
が予期されるときに送信できますが、受信側コードが既知の型の一覧に含める KnownTypeAttribute を使用している場合にのみ送信できます。
アプリケーション間でパラメーターと戻り値を渡す場合、予期される型がインターフェイスの場合、予期される型が Object型であるのと同じです。 すべての型は最終的に Objectから派生するため、すべてのデータ コントラクトは最終的に Objectのデータ コントラクトから派生します。 したがって、インターフェイスが必要な場合は、任意のデータ コントラクト型を渡すことができます。 インターフェイスを正常に操作するには、追加の手順が必要です。詳細については、「 データ コントラクトの既知の型」を参照してください。