4

我为我们的系统制作了一个小 CQRS API 我尝试使用 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 T 触发

此代码因参数不匹配异常而失败

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
  • 执行方法在抽象类中声明为public virtual void Execute(TCommand command)
  • TestCommand 实现抽象类命令
  • 奇怪的是,如果我静态地将它们声明为强类型,则相同的处理程序和命令可以工作,最后一个例子(在现实世界的例子中,我在构造函数中有依赖关系

    编辑2

  • 堆栈跟踪

在 CallSite.Target(Closure , CallSite , Object , Command ) 在 System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1](CallSite 站点, T0 arg0, T1 arg1) 在 XXX.Business.Command.CommandHandlerInvoker.Invoke(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) 在 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 个参数)在 System.Web.Mvc.ControllerActionInvoker.<> c_DisplayClass15.b _12() 在 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter 过滤器,ActionExecutingContext preContext,Func`1 延续)

  • 例外

最好的重载方法匹配 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 回答