8

BaseTypeサービスが、派生した型を実際に知らなくても受け入れて返すことができるようにしたいと考えています。この優れたブログ投稿 から、SharedTypeResolverDataContractResolverに基づくカスタムを使用したソリューションをほぼ手に入れました。

パズルの欠けているピースは、サービスが処理する型が共有されておらず、サービスに認識されていない可能性があるということですが、それでもそれらを受け入れて、型がどうあるべきかを認識したいと考えています。スタックとして機能するサービスの次の例を思いつきました。BaseTypeを使用しSharedTypeResolver、型がクライアントとサーバー間で共有されている場合は、から派生した型をプッシュおよびポップできます。

[DataContract]
public class BaseType
{
    [DataMember]
    public string SomeText { get; set; }

    public override string ToString()
    {
        return this.GetType().Name + ": " + this.SomeText;
    }
}

[DataContract]
public class DerivedType : BaseType
{
    [DataMember]
    public int SomeNumber { get; set; }

    public override string ToString()
    {
        return base.ToString() + ", " + this.SomeNumber;
    }
}

[ServiceContract]
public interface ITypeStack
{
    [OperationContract]
    void Push(BaseType item);

    [OperationContract]
    BaseType Pop();
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class TypeStackService : ITypeStack
{
    private Stack<BaseType> stack = new Stack<BaseType>();

    public void Push(BaseType item)
    {
        this.stack.Push(item);
    }

    public BaseType Pop()
    {
        return this.stack.Pop();
    }
}

これは明らかに、私が抱えている問題の非常に単純化された例です。クライアントは、クライアントとサーバーの両方がそれらを知っているため、非常に陽気にプッシュおよびポップできBaseTypeますが、サービスが知らないクライアントがプッシュすると、予想どおりエラーが発生します。DerivedTypeUnsharedType

メッセージのデシリアライズ中にフォーマッタが例外をスローしました: パラメータ http://tempuri.org/:itemのデシリアライズ中にエラーが発生しました。InnerException メッセージは、「行 1 の位置 316 のエラーです。要素 ' http://tempuri.org/:item ' には、名前 'TestWcfClient、Version=1.0.0.0、Culture=neutral、PublicKeyToken= にマップされる型のデータが含まれています」 null:TestWcfClient.UnsharedType'. デシリアライザーは、この名前にマップされる型を認識しません。名前 'TestWcfClient.UnsharedType' と名前空間 'TestWcfClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.' に対して null 以外の値を返すように、DataContractResolver の ResolveName メソッドの実装を変更することを検討してください。

私の現在の考えは、共有されていない型からの値を保持するために追加IExtensibleDataObjectし、アイテムがプッシュされたときに逆シリアルBaseType化で非共有型をサービスのように見せることです。BaseTypeアイテムがポップされるときは、逆のことが起こる必要があります。どうすればいいのかわかりません。可能なアプローチに関するこれまでの私の考え:

  • DataContractResolverを含む可能性のあるさらなるカスタマイズTypeDelegator
  • IDataContractSurrogate非共有型の代わりに使用する
  • アイテムがプッシュされたときにサービスが受け取ったシリアル化された XML を何らかの方法で保持し、アイテムがポップされたときに応答でこれを使用します。
  • メッセージ インスペクタを使用してメッセージを操作する

これらのいずれかが機能するかどうか、何が関係するのか、または何が最善の解決策であるかはわかりません。あなたは?

4

1 に答える 1