1

次のシナリオでは、クライアント側でシリアル化の問題が発生しています。

サービスコードに次のクラスとメソッドがあるとしましょう

[DataContract]
public class Derived
{
    [DataMember]
    public string A { get; set; }

    [DataMember]
    public string B { get; set; }

    [DataMember]
    public string C { get; set; }

    [DataMember]
    public string D { get; set; }
}

サービスインターフェイスにはメソッドがあります

    [OperationContract]
    Derived GetDerived();

メソッドの実装 -

public Derived GetDerived()
{
    var d = new Derived() {A = "A", B = "B", C = "C", D = "D"};
    return d;
}

この WCF サービスでは、(サービス参照を追加して) クライアント プロキシを作成し、GetDerived() 呼び出しを実行すると、すべて正常に動作します。

サービスコードのエンティティを少し変更しましょう

[DataContract]
public class Base
{
    [DataMember]
    public string B { get; set; }
}

[DataContract]
public class Derived : Base
{
    [DataMember]
    public string A { get; set; }        

    [DataMember]
    public string C { get; set; }

    [DataMember]
    public string D { get; set; }
}

この場合、新しい基本クラスを作成し、プロパティ「B」を基本クラスに移動しました。クライアント側で同じ古いプロキシを使用して、GetDerived 呼び出しを行うと、クライアント側で適切にシリアル化された A の値が表示されません。ただし、旧バージョンと現バージョンの SOAP メッセージは同じです (順序のみが変更されています)。このhttp://msdn.microsoft.com/en-us/library/ms729813.aspxの記事に出くわし、順序について説明しました。「B」を基本クラスに移動したため、派生クラスでの順序を制御する方法がわかりません。

この問題の回避策はありますか? これにより、クライアントへの下位互換性が失われます。

一方、新しいプロパティを追加すると、たとえば C1 を派生クラス (または既存のクラス) に追加すると、順序も変更されます。これがクライアントを壊さないのはなぜですか?先ほど述べたシナリオとは異なります。

4

1 に答える 1

0

上記の例を使用して、派生クラスでプロパティ「B」をオーバーロードし、Base クラスを参照するようにしました (私は VB で作業しています。申し訳ありません)。

#region "This shenanigans prevents breaking the contract when moving some properties to the base class.
    <DataMember()> Public Overloads Property B() As String
        Get
            Return MyBase.B
        End Get
        Set(value As String)
            MyBase.B = value
        End Set
    End Property
#End Region

このようにして、基本クラスのメソッドは引き続き B で動作できます。wcf のバージョン管理を実装する必要がある場合、またはコントラクトを変更する必要がある場合は、派生クラスでそのオーバーロードを取り除くことができ、すべてが機能するはずです。

-JG

于 2015-10-07T02:02:55.887 に答える