上位互換性のあるデータ コントラクト

Windows Communication Foundation (WCF) データ コントラクト システムの特長の 1 つは、コントラクトが、他に影響を及ぼさずに、時間の経過と共に進化できることです。 つまり、古いバージョンのデータ コントラクトを使用するクライアントが同じデータ コントラクトの新しいバージョンのサービスと通信したり、新しいバージョンのデータ コントラクトを使用するクライアントが同じデータ コントラクトの古いバージョンと通信したりできます。 詳細については、「ベスト プラクティス: データ コントラクトのバージョン管理」を参照してください。

バージョン管理機能の大半は、既存のデータ コントラクトの新しいバージョンが作成されたときに、必要に応じて適用できます。 ただし、ラウンド トリップ というバージョン管理機能は、正しく動作するように最初のバージョンから型に組み込んでおく必要があります。

ラウンド トリップ

ラウンド トリップは、データ コントラクトの新しいバージョンから古いバージョンにデータが渡され、新しいバージョンに戻されるときに発生します。 ラウンド トリップでは、データの損失がないことが保証されます。 ラウンド トリップを有効にすると、データ コントラクト バージョン管理モデルによってサポートされる将来の変更に関して、型の上位互換性が保たれます。

特定の型のラウンド トリップを有効にするには、この型に IExtensibleDataObject インターフェイスを実装する必要があります。 このインターフェイスには、(ExtensionData 型を返す) ExtensionDataObject プロパティが含まれます。 このプロパティにより、現在のバージョンでは未知の、今後使用されるデータ コントラクトの任意のデータが格納されます。

次のデータ コントラクトは、将来の変更に対して上位互換性がありません。

[DataContract]
public class Person
{
    [DataMember]
    public string fullName;
}
<DataContract()> _
Public Class Person
    <DataMember()> _
    Public fullName As String
End Class

将来の変更 (たとえば、"phoneNumber" という名前の新しいデータ メンバーを追加する) に対して互換性を確保するには、IExtensibleDataObject インターフェイスを次のように実装します。

[DataContract]
public class Person : IExtensibleDataObject
{
    [DataMember]
    public string fullName;
    private ExtensionDataObject theData;

    public virtual ExtensionDataObject ExtensionData
    {
        get { return theData; }
        set { theData = value; }
    }
}
<DataContract()> _
Public Class Person
    Implements IExtensibleDataObject
    <DataMember()> _
    Public fullName As String
    Private theData As ExtensionDataObject


    Public Overridable Property ExtensionData() As _
     ExtensionDataObject Implements _
     IExtensibleDataObject.ExtensionData
        Get
            Return theData
        End Get
        Set
            theData = value
        End Set
    End Property
End Class

WCF インフラストラクチャが、元のデータ コントラクトに含まれないデータを検出すると、このデータはプロパティに格納され、維持されます。 データは一時的に格納されるだけで、処理されることはありません。 オブジェクトを発生元に返すと、元の (未知の) データも返されます。 したがって、データが失われることなく、元のエンドポイントとの間でラウンド トリップ (往復) が行われます。 ただし、発生元のエンドポイントでデータを処理する必要がある場合、この要求は満たされないため、このエンドポイントでは何らかの方法で変更を検出して対応する必要があることに注意してください。

ExtensionDataObject 型にはパブリックなメソッドやプロパティはありません。 そのため、ExtensionData プロパティ内に格納されているデータに直接アクセスすることはできません。

ラウンド トリップ機能は、ignoreExtensionDataObject コンストラクターで trueDataContractSerializer に設定する、または IgnoreExtensionDataObjecttrue プロパティを ServiceBehaviorAttribute に設定することで無効にできます。 この機能を無効にすると、デシリアライザーが ExtensionData プロパティを設定しないため、シリアライザーはプロパティの内容を出力しません。

関連項目