动态关键字不适用于IoC,但经典反射确实如此

时间:2012-10-31 13:06:03

标签: c# dynamic reflection

我为我们的系统制作了一个小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是我们的Io​​C(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());

编辑:在评论中回答问题的更多信息

  • handlerType是一个实现抽象类CommandHandler<TCommand> where TCommand : Command
  • 的具体类
  • execute方法在抽象类中声明为public virtual void Execute(TCommand command)
  • TestCommand实现抽象类命令
  • 奇怪的是,如果我静态地声明它们是强类型的,那么相同的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是具体类

1 个答案:

答案 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)的固定签名