首先,对于模糊的问题标题感到抱歉。我想不出更精确的。
鉴于这些类型:
{ TCommand : ICommand }
«interface» «interface» /
+-----------+ +----------------------/----+
| ICommand | | ICommandHandler<TCommand> |
+-----------+ +---------------------------+
^ | Handle(command: TCommand) |
| +---------------------------+
| ^
| |
+------------+ +-------------------+
| FooCommand | | FooCommandHandler |
+------------+ +-------------------+
^
|
+-------------------+
| SpecialFooCommand |
+-------------------+
我想编写一个Dispatch
接受任何命令并将其发送到适当的ICommandHandler<>
. 我认为使用 DI 容器(Autofac)可能会大大简化从命令类型到命令处理程序的映射:
void Dispatch<TCommand>(TCommand command) where TCommand : ICommand
{
var handler = autofacContainer.Resolve<ICommandHandler<TCommand>>();
handler.Handle(command);
}
假设 DI 容器知道上面显示的所有类型。现在我打电话给:
Dispatch(new SpecialFooCommand(…));
实际上,这将导致 Autofac 抛出 a ComponentNotRegisteredException
,因为没有ICommandHandler<SpecialFooCommand>
可用的。
然而,理想情况下,我仍然希望 aSpecialFooCommand
由可用的最匹配的命令处理程序处理,即。上面例子中的 a FooCommandHandler
。
是否可以为此定制 Autofac,也许使用自定义注册源?
PS:我知道可能存在阻碍协变/逆变的基本问题(如下例所示),唯一的解决方案可能是根本不使用泛型的解决方案......但我会如果可能的话,想坚持使用泛型类型。
ICommandHandler<FooCommand> fooHandler = new FooCommandHandler(…);
ICommandHandler<ICommand> handler = fooHandler;
// ^
// doesn't work, types are incompatible