どうしても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がオブジェクトを返すことではありません。これは、ジェネリックから非ジェネリックへの変換シナリオに影響を与えるクラス/タイプの設計上の問題です。