2

マーカー インターフェイスを実装する (または基本クラスから派生する可能性がある) コマンドを使用できるコマンド プロセッサを構築しようとしています。プロセッサは、処理を要求されたコマンドを処理します。ただし、 Resolve(Type) がオブジェクトを返すため、真のジェネリック型の解決に苦労しています。可能であれば、これをキャストする方法がわかりませんか?

public void Process(ICommand command)
{
    var c = command.GetType();
    var t = typeof(ICommandHandler<>).MakeGenericType(new[] { c });
    var o = container.Resolve(t);
    //((ICommandHandler)o).Handle(command);  *** This doesn't work
}

呼び出しコードは次のようになります -

Dispatcher.Process(new SomeCommand(Guid.NewGuid(),"Param1",12345));
4

2 に答える 2

3

どうしてもICommandHandler<T>.Handleメソッドを呼び出す必要があり、システムの設計を他に制御できない場合は、リフレクションが唯一の選択肢になる可能性があります。ジェネリックから非ジェネリックへの切り替えに対処するための優れた方法はありません。

それ以外の場合は、いくつかのオプションがあります。

まず、Dispatcher.Processジェネリックにできる場合は、すべてのキャストを保存できます。

public static class Dispatcher
{
  public static void Process<T>(T command) where T : ICommand
  {
    var handler = container.Resolve<ICommandHandler<T>>();
    handler.Handle(command);
  }
}

これは、私が実際に見たこのような問題に対するかなり一般的な解決策です。

それができない場合は、インターフェイスに非ジェネリックベースインターフェイスを実装させるICommandHandler<T>ICommandHandlerことができる場合があります。

public interface ICommandHandler
{
  void Handle(ICommand command);
}

public interface ICommandHandler<T> : ICommandHandler
{
  void Handle(T command);
}

この後者の場合、強い型のコマンドハンドラーの実装を切り替えて、一般的な処理または基本的な処理のために同じ内部ロジックを呼び出す必要があります。そうしないと、呼び出しに基づいて異なる処理が行われることになります。これは悪いことです。

public class SomeCommandHandler : ICommandHandler<SomeCommand>
{
  public void Handle(ICommand command)
  {
    var castCommand = command as SomeCommand;
    if(castCommand == null)
    {
      throw new NotSupportedException("Wrong command type.");
    }
    // Hand off to the strongly-typed version.
    this.Handle(castCommand);
  }

  public void Handle(SomeCommand command)
  {
    // Here's the actual handling logic.
  }
}

次に、強く型付けICommandHandler<T>されたキャストを解決するとICommandHandler(質問のサンプルコードに示されているように)、機能します。

これもかなり一般的な解決策ですが、更新されたAPIが追加されていたジェネリックスが利用可能になる前に存在していたシステムでより多く見られました。

ただし、ここでのすべての場合において、問題はAutofacがオブジェクトを返すことではありません。これは、ジェネリックから非ジェネリックへの変換シナリオに影響を与えるクラス/タイプの設計上の問題です。

于 2012-09-10T15:06:56.510 に答える
2

リフレクションを使用する - しかし、これはこれにアプローチする最良の方法ですか?

    public void Process(Command command)
    {
        var c = command.GetType();
        var ot = typeof(ICommandHandler<>);
        var type = ot.MakeGenericType(new[] { c });
        var mi = type.GetMethod("Handle");
        var o = container.Resolve(type);
        mi.Invoke(o, new object[] { command });
    }
于 2012-09-09T13:55:19.443 に答える