gpt4 book ai didi

c# - 使用通用协方差/逆变自定义 Autofac 的组件分辨率/问题

转载 作者:IT王子 更新时间:2023-10-29 04:48:57 28 4
gpt4 key购买 nike

首先,对于模糊的问题标题感到抱歉。我想不出一个更精确的。

给定这些类型:

                                                     { 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 抛出 ComponentNotRegisteredException , 因为没有 ICommandHandler<SpecialFooCommand>可用。

理想情况下,我仍然想要一个 SpecialFooCommand由可用的最接近匹配的命令处理程序处理,即。通过 FooCommandHandler在上面的例子中。

能否为此定制 Autofac,或许使用定制注册源?


P.S.:我知道可能存在协变/逆变的基本问题(如以下示例所示),唯一的解决方案可能不是完全使用泛型...但如果可能的话,我想坚持使用泛型。

ICommandHandler<FooCommand> fooHandler = new FooCommandHandler(…);
ICommandHandler<ICommand> handler = fooHandler;
// ^
// doesn't work, types are incompatible

最佳答案

这不是一个真正公平的答案,因为自从您发布问题后我已经扩展了 Autofac...:)

根据 Daniel 的回答,您需要将 in 修饰符添加到 ICommandHandlerTCommand 参数中:

interface ICommandHandler<in TCommand>
{
void Handle(TCommand command);
}

Autofac 2.5.2 现在包含一个 IRegistrationSource 以启用逆变 Resolve() 操作:

using Autofac.Features.Variance;

var builder = new ContainerBuilder();
builder.RegisterSource(new ContravariantRegistrationSource());

注册此源后,将查找由具有单个 in 参数的通用接口(interface)表示的服务,同时考虑变体实现:

builder.RegisterType<FooCommandHandler>()
.As<ICommandHandler<FooCommand>>();

var container = builder.Build();
container.Resolve<ICommandHandler<FooCommand>>();
container.Resolve<ICommandHandler<SpecialFooCommand>>();

Resolve() 的两次调用都将成功检索 FooCommandHandler

如果您无法升级到最新的 Autofac 软件包,请从 http://code.google.com/p/autofac/source/browse/src/Source/Autofac/Features/Variance/ContravariantRegistrationSource.cs 获取 ContravariantRegistrationSource - 它应该针对任何最近的 Autofac 构建进行编译。

关于c# - 使用通用协方差/逆变自定义 Autofac 的组件分辨率/问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7010236/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com