4

システム用に小さなCQRSAPIを作成しましたが、dynamicキーワードを使用してリフレクションコードを置き換えようとしましたが、機能しません

各コマンドハンドラーはCommandHandler<TCommand>、メソッドを備えた汎用ですvoid Execute(TCommand Command)

リフレクションで動作します

public void Invoke(Contracts.Commands.Command command)
{
    var handlerType = types[command.GetType()];

    var handler = kernel.Get(handlerType);
    var method = handlerType.GetMethod("Execute");
    method.Invoke(handler, new object[] { command });
}

Kernel.Getkernel.Get<T>IoC(Ninject)の型なしバージョンです。これは機能し、一般的なメソッドExecute of Tfires

このコードは引数の不一致の例外で失敗します

public void Invoke(Contracts.Commands.Command command)
{
    var handlerType = types[command.GetType()];

    dynamic handler = kernel.Get(handlerType);
    handler.Execute(command);
}

タイプを静的に宣言すると、動的に機能します

dynamic handler = new TestCommandHandler();
handler.Execute(new TestCommand());

編集:コメントの質問に答えるためのいくつかのより多くの情報

  • handlerTypeは、抽象クラスを実装する具象クラスです。CommandHandler<TCommand> where TCommand : Command
  • executeメソッドは、抽象クラスで次のように宣言されます。public virtual void Execute(TCommand command)
  • TestCommandは、抽象クラスコマンドを実装します
  • 奇妙なことに、最後の例である強い型を静的に宣言すると、同じハンドラーとコマンドが機能します(実際の例では、コンストラクターに依存関係がありますが

    edit2

  • スタックトレース

CallSite.Target(Closure、CallSite、Object、Command)at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2 [T0、T1](CallSite site、T0 arg0、T1 arg1)at XXX.Business.Command.CommandHandlerInvoker.Invoke(Command command) C:\ XXX.Business \ Command \ CommandHandlerInvoker.cs:line 29 at XXX.Web.XXXService.Execute(Command command)in C:\ XXX.Web \ ExfiService.svc.cs:line 29 at XXX.Web.Controllers .ComplianceController.XXX(XXXViewModel viewModel)in C:\ XXX.Web \ Controllers \ XXXController.cs:line 52 at lambda_method(Closure、ControllerBase、Object [])at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller、Object []パラメータ)System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext、IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2つのパラメーター)atSystem.Web.Mvc.ControllerActionInvoker。<>c_ DisplayClass15.b _12()at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter、ActionExecutingContext preContext、Func`1 continuation)

  • 例外

オーバーロードされたメソッドの最適な一致 XXX.Business.Command.CommandHandler<XXX.Contracts.Commands.TestCommand>.Execute(XXX.Contracts.Commands.TestCommand)' has some invalid arguments

エラーメッセージは、Tの抽象クラスが具象クラスではなく、上記のコードのhandlerTypeが具象クラスであることを示しています。

4

1 に答える 1

3

コードを次のように変更する必要があります。

public void Invoke(Contracts.Commands.Command command)
{
    var handlerType = types[command.GetType()];

    dynamic handler = kernel.Get(handlerType);
    dynamic cmd = command;
    handler.Execute(cmd);
}

commandパラメータが最初に動的ローカル変数 ( ) に割り当てられていることに注意してくださいcmd。これにより、 の型を実行時に評価できるようになり、呼び出しを真に動的cmdに保つことができます。Executeこのようにしない場合、Executeメソッドは次の固定シグネチャを持つと想定されますExecute(Contracts.Commands.Command command)

于 2012-11-01T07:41:41.677 に答える