Simple Injector注册将开放和封闭泛型实现组合的组合。

4
我正在创建验证装饰器来处理我的指令,但是我在使用 Simple Injector DI 容器注册类型时遇到了困难。
情况如下:
- 目前只有一个验证器可以应用于所有的指令,即 DataAnnotationsCommandValidator<TCommand>。 - 我还有一些特定指令所需的验证器。例如,CreateRefreshTokenCommandValidator 实现了 ICommandValidator<CreateRefreshTokenCommand> 接口。
根据 Simple Injector 文档,在这种情况下,应该创建一个 CompositeCommandValidator。我按照文档中提到的实现方式进行了操作,也就是说,我的 ValidationCommandHandlerDecorator 仍然依赖于 ICommandValidator<TCommand> 而不是 IEnumerable
接下来需要配置 Simple Injector 容器。我的当前配置如下:
_container.RegisterManyForOpenGeneric(
    typeof(ICommandValidator<>), 
    _container.RegisterAll,
    typeof (ICommandValidator<>).Assembly);

_container.RegisterAllOpenGeneric(
    typeof(ICommandValidator<>),
    typeof(DataAnnotationsCommandValidator<>));

_container.RegisterSingleOpenGeneric(
    typeof(ICommandValidator<>), 
    typeof(CompositeCommandValidator<>));

然而,当我调试应用程序时,只有特定的验证器被注入到CompositeCommandValidator中(我没有DataAnnotationsCommandValidator)。我尝试了几种不同的配置,但都无济于事。我应该如何配置Simple Injector才能获得正确的行为?

1个回答

2

Simple Injector v4更新说明:

// Register validators as sequence
_container.Collection.Register(
    typeof(ICommandValidator<>),
    typeof (ICommandValidator<>).Assembly);

// Append the data annotations validator as last element to the sequence
_container.Collection.Append(
    typeof(ICommandValidator<>),
    typeof(DataAnnotationsCommandValidator<>));

// Register the composite that will wrap the sequence.
_container.Register(
    typeof(ICommandValidator<>), 
    typeof(CompositeCommandValidator<>));

原始Simple Injector v2答案:

RegisterManyForOpenGeneric方法仅会扫描程序集以查找给定接口的非泛型实现,因为开放式泛型实现通常需要特殊处理。这里基本上有两个选项。

选项1:

var types = OpenGenericBatchRegistrationExtensions.GetTypesToRegister(
    _container,
    typeof (ICommandValidator<>),
    AccessibilityOption.PublicTypesOnly,
    typeof (ICommandValidator<>).Assembly)
    .ToList();

types.Add(typeof(DataAnnotationsValidator<>));

_container.RegisterAll(typeof(ICommandValidator<>), types);

在这里,我们使用GetTypesToRegister方法查找所有非泛型实现,将开放式泛型类型附加到此集合中,并使用RegisterAll注册整个集合。

您的第二个选项是将RegisterManyForOpenGenericAppendToCollection混合使用:

_container.RegisterManyForOpenGeneric(typeof(ICommandValidator<>), 
    _container.RegisterAll,
    typeof(ICommandValidator<>).Assembly);

// using SimpleInjector.Advanced;
_container.AppendToCollection(typeof(ICommandValidator<>),
    typeof(DataAnnotationsValidator<>));

谢谢!我从没想到过。我修改了你的答案,因为它几乎完全正确。 - Larrifax
@Larrifax:你需要注册这个的方式是因为设计决策将普通注册与集合注册分开的直接结果。 - Steven

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接