C# Dynamic关键字不适用于IoC,但classic reflection适用

C# Dynamic关键字不适用于IoC,但classic reflection适用,c#,dynamic,reflection,C#,Dynamic,Reflection,我为我们的系统制作了一个小小的CQRS API 我试图用dynamic关键字替换一些反射代码,但它不起作用 每个命令处理程序都是通用的CommandHandler,带有一个方法void Execute(TCommand命令) 通过反射,它可以工作 public void Invoke(Contracts.Commands.Command command) { var handlerType = types[command.GetType()]; var handler = ke

我为我们的系统制作了一个小小的CQRS API 我试图用dynamic关键字替换一些反射代码,但它不起作用

每个命令处理程序都是通用的
CommandHandler
,带有一个方法
void Execute(TCommand命令)

通过反射,它可以工作

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火灾

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

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

    dynamic handler = kernel.Get(handlerType);
    handler.Execute(command);
}
如果我静态声明它与dynamic一起工作的类型

dynamic handler = new TestCommandHandler();
handler.Execute(new TestCommand());
编辑:更多信息以回答评论中的问题

  • handlerType是一个具体的类,它实现了抽象类CommandHandler,其中TCommand:Command
  • execute方法在抽象类中声明为
    publicvirtualvoidexecute(TCommand命令)
  • TestCommand实现抽象类命令
  • 奇怪的是,如果我静态地声明它们是强类型的,那么同一个处理程序和命令也可以工作,最后一个例子(在现实世界的例子中,我在构造函数中有依赖项)

    edit2

  • 堆栈跟踪

目标(闭包、调用站点、对象、命令)位于 System.Dynamic.UpdateLegates.UpdateAndExecuteVoid2[T0,T1](调用站点 站点,T0 arg0,T1 arg1)位于 三十、 Command.CommandHandlerInvoker.Invoke(命令 命令)在 C:\XXX.Business\Command\CommandHandlerInvoker.cs:line 29在中的XXX.Web.XXXService.Execute(命令) C:\XXX.Web\ExfiService.svc.cs:第29行 三十、 Web.controller.ComplianceController.XXX(XXXViewModel 视图模型)中 C:\XXX.Web\Controllers\XXX控制器.cs:line 52在lambda_方法(闭包、控制器基、对象[])处 System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase 控制器,对象[]参数)位于 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext,IDictionary
2个参数)位于
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext
controllerContext,ActionDescriptor ActionDescriptor,IDictionary
2 参数)在 System.Web.Mvc.ControllerActionInvoker.c_DisplayClass15.b_12() 在 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter 筛选器,ActionExecutingContext预文本,函数'1(续)

  • 例外情况
匹配的最佳重载方法
XXX.Business.Command.CommandHandler.Execute(XXX.Contracts.Commands.TestCommand)”具有一些无效参数


错误消息指出T的抽象类不是具体类,但上面代码中的handlerType是具体类

您需要将代码更改为如下所示:

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

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

请注意,
命令
参数首先分配给一个动态局部变量(
cmd
)。这允许在运行时评估
cmd
的类型,并使对
Execute
的调用保持真正的动态;如果不这样做,则假定
Execute
方法具有固定签名
Execute(Contracts.Commands.Command)

请提供异常的完整堆栈跟踪。
handlerType
是一个接口?一个具体类?一个抽象类?并且
Execute
public?internal?protected?一个显式接口实现?或者…?同样地,
命令
TestCommand
dynamic
围绕a:accessibility和b:interfaces vs public Api展开。以下是无法重现您的问题的示例代码:。我将检查绑定是否正确,
Execute
是否具有您认为它具有的参数。我可以重现此错误,但只有在
CommandHandler.Execut(T)时才能重现此错误
获取一个不是类型
T
的参数-在您的例子中,如果
处理程序的泛型类型与
命令的类型不同,只需快速调试-也许您可以尝试查看
命令.GetType().Name
处理程序.GetType().Name
?确保
handler
的类型为
TestCommandHandler
,而不是
CommandHandler
(虽然,它应该可以工作……我仍然无法复制它)哈哈,我觉得自己像个白痴,我没有想过要尝试它!:P谢谢!