2

CQRSソリューションを構築しようとすると、次のコードでハンドラーを見つけて、Handle()メソッドを呼び出そうとしています。

以下のコードは機能しますが、すべてのIHandleCommand <>にHandleメソッドがあることがわかっている場合、リフレクションを使用するのは面倒です。これはコンパイル時に解決できると思います。

dynamicなんらかの方法で使用する必要がありますか?

public void SendCommand(Command command)
{
    Type handlerType = typeof(IHandleCommand<>).MakeGenericType(command.GetType());
    object handler = container.Resolve(handlerType);
    handler.GetType().GetMethod("Handle").Invoke(handler, new object[] { command });
}

上記で使用されている他のタイプは次のとおりです

public class Command {}

public class MyCommand : Command {}

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

public class MyCommandHandler : IHandleCommand<MyCommand>
{
    public void Handle(MyCommand command)   {}
}
4

3 に答える 3

0

コンテナー (私の場合は StructureMap) を使用してハンドラー インスタンスを取得するのと同様のものを作成しました。

その質問とその回答を確認してください: StructureMap は、すべての可能な具体的な実装に対してジェネリック型を登録します

于 2012-05-30T10:54:37.050 に答える
0

Autofac を使用して問題を解決しました。
これが私が最終的に得たものです

このインターフェースを想定

public interface IHandleCommand<T> where T : Command
{
  void Handle(T command);
}

サービスバスはこのようなものを呼び出します

private readonly IComponentContext container;

public InProcessBus(IComponentContext container)
{
  this.container = container;
}

public void Send<T>(T command) where T : Command
{
  if (command == null) throw new ArgumentNullException("Command");
  container.Resolve<IHandleCommand<T>>().Handle(command);
}

と私の Autofac CommandsHandlersModule

public class CommandsHandlersModule : Autofac.Module
{
  protected override void Load(ContainerBuilder builder)
  {
     builder.RegisterAssemblyTypes(typeof(CartCommandsHandler).Assembly)
       .AsClosedTypesOf(typeof(IHandleCommand<>))
       .SingleInstance();
   }
}

アプリから呼び出すよりも

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new CommandsHandlersModule());
于 2012-05-30T12:42:46.427 に答える
0

遊んだ後、いくつかの解決策を見つけました:

dynamic handler = container.Resolve(handlerType);
handler.Handle(command as dynamic);

しかし、コマンドをジェネリック メソッドに動的に送信すると、魔法を行う T のような実際の型として Command が取得されます。また、Handle() の呼び出しはコンパイル時に解決できます。次に、最初から問題であることが判明した一般的な共変キャストの必要はありません。

public void SendCommand(Command command)
{
    Invoke(command as dynamic);
}

private void Invoke<T>(T command) where T : Command
{
    var handler = container.Resolve<IHandleCommand<T>>();
    handler.Handle(command);
}

それは本当に素晴らしいですが、私はコマンドハンドラーを登録していないので、私はこれを使用します:

private void Invoke<T>(T command) where T : Command
{
    Type handlerType = CommandToHandlerType(command);
    var handler = (IHandleCommand<T>)container.Resolve(handlerType);
    handler.Handle(command);
}

CommandToHandlerType() は、T の IHandleCommand を実装する型のアセンブリを検索するだけです。

于 2012-05-31T12:01:17.283 に答える