2

一部のアプリケーションでは、Web エンドポイントのコンシューマーが、要求ごとにカスタマイズされた、返されたオブジェクト グラフに必要なプロパティのサブセットを指定できると便利です。呼び出し元は、クエリ文字列/要求で必要なプロパティを示します。タイプ構造ごとではなく、リクエストごとにシリアル化をカスタマイズする必要があります。これを解決する理想的な方法は思いつきません。理想的には、ビュー モデル (シリアル化するオブジェクト) に変更を強制せず、エンドポイントごとにこの機能を有効にするだけです (たとえば、エンドポイントに属性を配置することによって)。

現在、MVC4/Web Api などでこれを行う方法はありますが、理想的ではありません。コールバックがインスタンス/オブジェクトのみを提供し、コンテキスト (ユーザーが必要とするプロパティ、オブジェクト グラフ内の場所) を提供しないことを除けば、ビュー モデルを変更する必要はありません。1 つのタイプでフィルタリングするだけで問題ない場合、これは機能しますが (リクエスト グローバル HttpContext を使用する場合)、より一般的なソリューションで階層フィルタリングを実行したり、タイプが複数のレベルで表示される場合は機能しません。オブジェクトグラフ。

今のところ、これを行う方法の 1 つは、シリアル化されるビュー モデルの基本クラス/インターフェイスを用意してから、ISerializable を実装することです。また、独自の MediaTypeFormatter を記述する必要があるため、ストリーミング コンテキストに何かを詰め込んで、クエリ文字列で指定されたフィールドなどのフィルタリングに必要な作業を行い、便利な Path プロパティを持つライターにアクセスできます。プロパティ名の階層的および/またはワイルドカードフィルタリングを簡単に行うために使用できます。

ビュー モデル オブジェクトに触れずに方法はありません。シリアライザーに機能を追加する必要があります。1 つの方法は、ストリーミング コンテキストを ShouldSerialize コールバック シグネチャに追加することです (渡されたインスタンス オブジェクトの形式をオプションで指定してストリーミング コンテキストも含めることができない限り、おそらく JSONProperty インターフェイスに新しいメソッドが必要です)。プロパティ名でフィルタリングするためのロジックを追加するのは、まだ私たちの仕事です。もう 1 つの方法は、ロジックを JSonSerializerInternalWriter::ShouldSerialize メソッドに焼き付けて、シリアライゼーション設定で条件付きで機能を有効にすることです。

ビューモデルに触れずにこれを行う方法に関する他のアイデアはありますか?

4

1 に答える 1

0

考えられる 2 つの解決策

  1. 私の考えでは、ここで説明されているようにIContractResolverを使用しますが、何らかの方法でそれを制御する c'tor パラメーターを使用します。

    public class ShouldSerializeContractResolver : DefaultContractResolver { プライベート readonly bool _alwaysIncludeManager; public new static readonly ShouldSerializeContractResolver インスタンス = new ShouldSerializeContractResolver();

    public ShouldSerializeContractResolver(bool alwaysIncludeManager = true)
    {
        _alwaysIncludeManager = alwaysIncludeManager;
    }
    
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
    
        if (property.DeclaringType == typeof(Employee) && property.PropertyName == "Manager")
        {
            property.ShouldSerialize =
                instance =>
                {
                    Employee e = (Employee)instance;
                    return e.Manager != e || _alwaysIncludeManager;
                };
        }
    
        return property;
    }
    

    }

  2. より単純なものについては、シリアル化の直前に匿名オブジェクトに変換したことがあります。

-

List<Employee> employeeList = LoadEmployeeList();
bool alwaysIncludeManager = true; //Set by context
var outputList = employeeList.Select(x =>
    new
    {
        x.Name,
        Manager = (Manager != x || alwaysIncludeManager)
                    ? x.Manager : null
    });
//Then return this anonymous object, or serialize it
于 2014-09-09T15:39:27.840 に答える