如何解决与对象

时间:2016-02-01 18:43:58

标签: c# generics reflection castle-windsor

我有以下接口和类。

interface ICommand { ... }

class Command1 : ICommand { ... }

class Command1 : ICommand { ... }

interface IHandle<TCommand> where TCommand : ICommand
{
    IResult Handle(TCommand command);
}

Command1Handler : IHandle<Command1> { ... }

Command2Handler : IHandle<Command2> { ... }

Command1Handler和Command2Handler在Castle Widsor容器中注册。当我收到命令时,我想在容器中找到可以处理命令的Handler。

public IResult ProcessCommand(ICommand command)
{
    var handler = Container.Resolve //How to resolve based on command?
    return handler.Handle(command);
}

我不能打电话

Container.Resolve<IHandle<Command1>>() 

因为我不知道TCommand,如果我知道

Container.ResolveAll(typeof(IHandle<>))

我不知道哪个处理程序可以处理我的命令。

1 个答案:

答案 0 :(得分:0)

最好的选择是使用反射:

dynamic handler = container.Resolve(
    typeof(IHandler<>).MakeGenericType(cmd.GetType()));
handler.Handle(cmd);

但真正的答案是重构你的代码,你正在与类型系统作斗争。温莎在这里没有帮助,它可以让你引用正确的类型,但是当你打电话给IHandler<T>时,你仍然必须投射到正确的Handle(cmd)。使用通用方法会好得多:

void Handle<T>(ICommand<T> cmd) {
  var handler = container.Resolve<IHandler<T>>();
  handler.Handle(cmd);
}

interface ICommand<T> { }
class Command1 : ICommand<Command1> { }

或使用多态的魔力:

class BaseCommand<T> : ICommand<T> {
  public void FindAndExecuteHandler(IKernel kernel) {
    kernel.Resolve<IHandler<T>>().Handle(this);
  }
}

class Command1 : BaseCommand<Command1> { }

cmd1.FindAndExecuteHandler(container);

与你的问题非常相似的是找到给定模型的IValidator<T>,有很多关于SO的问题和各种解决方案 - 你可能想在这里做一些R&amp; D.