1

Json.NET シリアライザーを使用して Microsoft WebAPI を使用しており、コントローラー パラメーター バインディングを使用して、Castle DictionaryAdapter を JSON からの逆シリアル化されたオブジェクトとしてインスタンス化しようとしています。(これにより、JSON で特定のプロパティが null に設定されているかどうか、または JSON にないためにデフォルトで null に設定されているかどうかを、組み込みの解析およびバインディング メカニズムを放棄することなく検出できます。)

しかし、新しいオブジェクトが作成されてからコントローラーに渡されるまでの間に消えるため、機能していません。

コントローラーは、インターフェイス パラメーターを使用して宣言されます。

  public interface IMessageModel
  {
      string Message { get; set; }
  }
.
.
.
  public HttpResponseMessage Patch(IMessageModel model)

デシリアライザーで IMessageModel を実装する Castle DictionaryAdapter をインスタンス化する必要があります。

これを行うために、DictionaryAdapterFactory で構築され、Create() メソッドをオーバーライドして動的な Castle オブジェクトを返す CustomCreationConverter のサブクラスを作成しました。

  public class MessageModelConverter
      : CustomCreationConverter<IMessageModel>
  {
      private DictionaryAdapterFactory m_adapterFactory;
      public MessageModelConverter(DictionaryAdapterFactory adapterFactory)
      {
          m_adapterFactory = adapterFactory;
      }
      public override IMessageModel Create(Type objectType)
      {
          IMessageModel model = m_adapterFactory
              .GetAdapter<IMessageModel>(new Hashtable());
          return model;
      }
  }

次に、次のようなフォーマッタを HttpConfiguration オブジェクトに追加します。

  DictionaryAdapterFactory adapterFactory = new DictionaryAdapterFactory();
  config.Formatters.JsonFormatter.SerializerSettings.Converters
      .Add(new MessageModelConverter(adapterFactory));

デバッガーを使用して、MessageModelConverter が使用されていること、Create() が呼び出され、IMessageModel を実装するモデルのキャッスル プロキシを作成して返すことを確認できます。ただし、コントローラーが呼び出されると、モデル パラメーターは null になります。どういうわけか、インスタンス化されたクラスは、コンバーターでの作成とコントローラーでの使用の間に消えています。

しかし、IMessageModel を実装する具象クラスを使用するように Create を変更すると、すべてが正常に機能し、コントローラーにモデルが表示されます。

  public class MessageModel : IMessageModel
  {
      public string Message { get; set; }
  }
.
.
.
      public override IMessageModel Create(Type objectType)
      {
          IMessageModel model = new MessageModel();
          return model;
      }

または、次のように、IMessageModel を実装し、すべての呼び出しを別のインターフェイス オブジェクトに委譲するラッパーを宣言することもできます。

  public class MessageModelWrapper : IMessageModel
  {
      public IMessageModel ContainedModel;
      public MessageModelWrapper(IMessageModel containedModel)
      {
          ContainedModel = containedModel;
      }
      public string Message
      {
          get { return ContainedModel.Message; }
          set { ContainedModel.Message = value; }
      }
  }

次に、次のように Create() を実装します。

  public override IMessageModel Create(Type objectType)
  {
      IMessageModel model = m_adapterFactory
          .GetAdapter<IMessageModel>(new Hashtable());
      model = new MessageModelWrapper(model);
      return model;
  }

これにより、Castle DictionaryAdapter に密輸することができ、問題なく動作します。モデル ラッパーがコントローラーに到着し、ディクショナリ アダプター プロキシを抽出できます。

しかし、Castle DictionaryAdapter を作成して直接返すと、コントローラーはまだ null を取得します。

WebAPI が Castle DictionaryAdapter を嫌う理由は何ですか?

4

0 に答える 0