データ コントラクトの使用
データ コントラクト は、サービスとクライアントの間の正式な取り決めであり、交換されるデータが抽象的に記述されています。 つまり、クライアントとサービスが通信するために必要なのは同じデータ コントラクトだけで、同じ型を共有する必要はありません。 データ コントラクトは、パラメーターまたは戻り値の型ごとに、交換するためにシリアル化する (XML に変換する) 必要があるデータを正確に定義します。
データ コントラクトの基本
Windows Communication Foundation (WCF) により、データ コントラクト シリアライザーと呼ばれるシリアル化エンジンが既定で使用されて、データのシリアル化と逆シリアル化 (データと XML の間の変換) が行われます。 すべての .NET Framework プリミティブ型 (整数や文字列など) およびプリミティブ型として扱われる特定の型 (DateTime や XmlElementなど) は、準備なしでシリアル化できるため、既定のデータ コントラクトを持つと見なされます。 多くの .NET Framework 型にも、既存のデータ コントラクトがあります。 シリアル化できるすべての型の一覧については、「 Types Supported by the Data Contract Serializer」を参照してください。
新しい複合型を作成したら、シリアル化できるように、データ コントラクトを定義する必要があります。 既定では、 DataContractSerializer はデータ コントラクトを推測し、公開されている型をすべてシリアル化します。 その型の読み書き可能なパブリック プロパティおよびパブリック フィールドは、すべてシリアル化されます。 IgnoreDataMemberAttributeを使用することにより、メンバーがシリアル化されないようにすることができます。 また、 DataContractAttribute 属性および DataMemberAttribute 属性を使用して、データ コントラクトを明示的に作成することもできます。 これを行うには、通常、その型に DataContractAttribute 属性を適用します。 この属性は、クラス、構造体、および列挙体に適用できます。 次に、データ コントラクト型の各メンバーに DataMemberAttribute 属性を適用して、それが データ メンバーであること、つまり、シリアル化する必要があることを示す必要があります。 詳細については、「シリアル化可能な型」を参照してください。
例
ServiceContractAttribute 属性と OperationContractAttribute 属性が明示的に適用されたサービス コントラクト (インターフェイス) の例を次に示します。 この例は、プリミティブ型はデータ コントラクトを必要としないのに対し、複合型は必要とすることを示しています。
[ServiceContract]
public interface ISampleInterface
{
// No data contract is required since both the parameter
// and return types are primitive types.
[OperationContract]
double SquareRoot(int root);
// No Data Contract required because both parameter and return
// types are marked with the SerializableAttribute attribute.
[OperationContract]
System.Drawing.Bitmap GetPicture(System.Uri pictureUri);
// The MyTypes.PurchaseOrder is a complex type, and thus
// requires a data contract.
[OperationContract]
bool ApprovePurchaseOrder(MyTypes.PurchaseOrder po);
}
<ServiceContract()> _
Public Interface ISampleInterface
' No data contract is required since both the parameter and return
' types are both primitive types.
<OperationContract()> _
Function SquareRoot(ByVal root As Integer) As Double
' No Data Contract required because both parameter and return
' types are marked with the SerializableAttribute attribute.
<OperationContract()> _
Function GetPicture(ByVal pictureUri As System.Uri) As System.Drawing.Bitmap
' The MyTypes.PurchaseOrder is a complex type, and thus
' requires a data contract.
<OperationContract()> _
Function ApprovePurchaseOrder(ByVal po As MyTypes.PurchaseOrder) As Boolean
End Interface
次の例では、 MyTypes.PurchaseOrder
型のデータ コントラクトが作成され、 DataContractAttribute と DataMemberAttribute 属性がクラスとそのメンバーに適用されるかを示します。
namespace MyTypes
{
[DataContract]
public class PurchaseOrder
{
private int poId_value;
// Apply the DataMemberAttribute to the property.
[DataMember]
public int PurchaseOrderId
{
get { return poId_value; }
set { poId_value = value; }
}
}
}
Namespace MyTypes
<System.Runtime.Serialization.DataContractAttribute()> _
Public Class PurchaseOrder
Private poId_value As Integer
' Apply the DataMemberAttribute to the property.
<DataMember()> _
Public Property PurchaseOrderId() As Integer
Get
Return poId_value
End Get
Set
poId_value = value
End Set
End Property
End Class
End Namespace
Notes
以下に、データ コントラクトを作成する際に考慮する必要がある項目を示します。
IgnoreDataMemberAttribute 属性は、マークされていない型で使用した場合にのみ受け入れられます。 これには、 DataContractAttribute、 SerializableAttribute、 CollectionDataContractAttribute、 EnumMemberAttribute のいずれかの属性でマークされていない型、または他の方法 ( IXmlSerializableなど) でシリアル化可能としてマークされた型が含まれます。
DataMemberAttribute 属性は、フィールドおよびプロパティに適用できます。
メンバーのアクセシビリティ レベル (内部、プライベート、保護、またはパブリック) は、データ コントラクトに影響しません。
DataMemberAttribute 属性が静的メンバーに適用されている場合は無視されます。
シリアル化中には、プロパティのデータ メンバーがシリアル化対象のプロパティの値を取得できるように、プロパティ取得コードが呼び出されます。
逆シリアル化中には、まず初期化されていないオブジェクトが、その型のコンストラクターを呼び出さずに作成されます。 次に、すべてのデータ メンバーが逆シリアル化されます。
逆シリアル化中には、プロパティのデータ メンバーが、プロパティを逆シリアル化されている値に設定できるように、プロパティ設定コードが呼び出されます。
データ コントラクトが有効であるためには、すべてのデータ メンバーをシリアル化できる必要があります。 シリアル化できるすべての型の一覧については、「 Types Supported by the Data Contract Serializer」を参照してください。
ジェネリック型は、非ジェネリック型とまったく同じように処理されます。 ジェネリック パラメーターに対する特別な要件はありません。 たとえば、次の型について考えます。
[DataContract]
public class MyGenericType1<T>
{
// Code not shown.
}
<DataContract()> _
Public Class MyGenericType1(Of T)
' Code not shown.
End Class
この型は、ジェネリック型パラメーター (T
) に使用される型をシリアル化できるかどうかに関係なくシリアル化できます。 すべてのデータ メンバーをシリアル化できる必要があるため、次の型をシリアル化できるのは、ジェネリック型パラメーターもシリアル化できる場合だけです。次のコード例を参照してください。
[DataContract]
public class MyGenericType2<T>
{
[DataMember]
T theData;
}
<DataContract()> _
Public Class MyGenericType2(Of T)
<DataMember()> _
Dim theData As T
End Class
データ コントラクトを定義する WCF サービスのコード サンプル全体については、「 Basic Data Contract 」のサンプルを参照してください。