簡體   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