首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >泛型协变强制转换或强制转换为实型

泛型协变强制转换或强制转换为实型
EN

Stack Overflow用户
提问于 2012-05-30 18:48:39
回答 3查看 325关注 0票数 2

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

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

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

代码语言:javascript
复制
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 });
}

下面是上面使用的其他类型

代码语言:javascript
复制
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)   {}
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-31 20:01:17

在尝试之后,我找到了一些解决方案:

代码语言:javascript
复制
dynamic handler = container.Resolve(handlerType);
handler.Handle(command as dynamic);

但是如果我把命令作为动态的发送给一个泛型方法,我会得到command,因为它是T的真实类型。此外,对Handle()的调用可以在编译时解析。这样就不需要泛型协变类型了,这从一开始就是个问题。

代码语言:javascript
复制
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);
}

它真的很好,但我不会完全采用该解决方案,因为我没有注册命令处理程序,我将使用以下代码:

代码语言:javascript
复制
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的类型

票数 0
EN

Stack Overflow用户

发布于 2012-05-30 18:54:37

我做了一些类似的事情,我使用一个容器(在我的例子中是StructureMap)从其中获取处理程序实例。

请查看该问题及其答案:StructureMap register generic types against all possible concrete implementations

票数 0
EN

Stack Overflow用户

发布于 2012-05-30 20:42:46

我用Autofac解决了这个问题。

这就是我最终得到的结果

假设此接口

代码语言:javascript
复制
public interface IHandleCommand<T> where T : Command
{
  void Handle(T command);
}

Servicebus将调用类似如下的内容

代码语言:javascript
复制
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

代码语言:javascript
复制
public class CommandsHandlersModule : Autofac.Module
{
  protected override void Load(ContainerBuilder builder)
  {
     builder.RegisterAssemblyTypes(typeof(CartCommandsHandler).Assembly)
       .AsClosedTypesOf(typeof(IHandleCommand<>))
       .SingleInstance();
   }
}

而不是从你的应用程序调用

代码语言:javascript
复制
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new CommandsHandlersModule());
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10814768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档