我为我们的系统制作了一个小CQRS API 我尝试使用动态关键字替换一些反射代码,但它不起作用
每个命令处理程序都是Generic 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.Get
是我们的IoC(Ninject)中kernel.Get<T>
的无类型版本。这有效,并且通用方法执行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());
编辑:在评论中回答问题的更多信息
CommandHandler<TCommand> where TCommand : Command
public virtual void Execute(TCommand command)
奇怪的是,如果我静态地声明它们是强类型的,那么相同的Handler和命令也可以工作,最后一个例子(在现实世界的例子中,我在构造函数中有依赖关系
EDIT2
堆栈跟踪
在CallSite.Target(Closure,CallSite,Object,Command)处 System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2 [T0,T1](调用点 site,T0 arg0,T1 arg1)at XXX.Business.Command.CommandHandlerInvoker.Invoke(命令 命令)in C:\ XXX.Business \ COMMAND \ CommandHandlerInvoker.cs:行 29.在XXX.Web.XXXService.Execute(命令命令)中 C:\ XXX.Web \ ExfiService.svc.cs:第29行 XXX.Web.Controllers.ComplianceController.XXX(XXXViewModel viewModel)中 C:\ XXX.Web \控制器\ XXXController.cs:行 52在lambda_method(Closure,ControllerBase,Object [])at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller,Object []参数)at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext,IDictionary
2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
2 参数)at System.Web.Mvc.ControllerActionInvoker&LT;&GT; C_ DisplayClass15.b _12() 在 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是具体类
答案 0 :(得分: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)
的固定签名