繁体   English   中英

通用协变强制转换或强制转换为实型

[英]Generic covariant cast or cast to real type

尝试构建CQRS解决方案时,我有以下代码尝试找到Handler,然后调用Handle()方法。

下面的代码有效,但是当我们知道所有IHandleCommand <>都有Handle方法时,使用反射很烦人,我相信这可以在编译时解决!

我必须以某种方式使用dynamic吗?

public void SendCommand(Command command)
{
    Type handlerType = typeof(IHandleCommand<>).MakeGenericType(command.GetType());
    object handler = container.Resolve(handlerType);
    handler.GetType().GetMethod("Handle").Invoke(handler, new object[] { command });
}

这是上面使用的其他类型

public class Command {}

public class MyCommand : Command {}

public interface IHandleCommand<T>
{
void Handle(T command);
}

public class MyCommandHandler : IHandleCommand<MyCommand>
{
    public void Handle(MyCommand command)   {}
}

我做了一些类似于使用容器(在本例中为StructureMap)从中获取处理程序实例的操作。

查看该问题及其答案: StructureMap针对所有可能的具体实现注册通用类型

我用Autofac解决了这个问题。
这就是我最终得到的

假设这个介面

public interface IHandleCommand<T> where T : Command
{
  void Handle(T command);
}

Servicebus将调用这样的内容

private readonly IComponentContext container;

public InProcessBus(IComponentContext container)
{
  this.container = container;
}

public void Send<T>(T command) where T : Command
{
  if (command == null) throw new ArgumentNullException("Command");
  container.Resolve<IHandleCommand<T>>().Handle(command);
}

和我的Autofac CommandsHandlersModule

public class CommandsHandlersModule : Autofac.Module
{
  protected override void Load(ContainerBuilder builder)
  {
     builder.RegisterAssemblyTypes(typeof(CartCommandsHandler).Assembly)
       .AsClosedTypesOf(typeof(IHandleCommand<>))
       .SingleInstance();
   }
}

比您通过应用调用

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new CommandsHandlersModule());

玩了之后,我发现了一些解决方案:

dynamic handler = container.Resolve(handlerType);
handler.Handle(command as dynamic);

但是,如果我以动态方式将命令发送给泛型方法,我将获得Command,因为它是T的实类型,可以用来处理魔术。 同样,对Handle()的调用也可以在编译时解决。 然后就不需要泛型协变转换,这从一开始就成为问题。

public void SendCommand(Command command)
{
    Invoke(command as dynamic);
}

private void Invoke<T>(T command) where T : Command
{
    var handler = container.Resolve<IHandleCommand<T>>();
    handler.Handle(command);
}

确实很好,但是由于我不提供命令处理程序,因此我不会完全采用该解决方案,我将使用以下命令:

private void Invoke<T>(T command) where T : Command
{
    Type handlerType = CommandToHandlerType(command);
    var handler = (IHandleCommand<T>)container.Resolve(handlerType);
    handler.Handle(command);
}

CommandToHandlerType()只是在程序集中搜索实现T的IHandleCommand的类型

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM