结合开放和封闭通用实现的Composite的简单注入器注册

时间:2014-08-22 10:10:36

标签: c# dependency-injection simple-injector

我正在为我的命令创建验证装饰器,但是我在使用Simple Injector DI容器注册类型时遇到了麻烦。

案例是:

  • 我(现在)应该始终应用一个验证器DataAnnotationsCommandValidator<TCommand>
  • 我还有几个应该应用于特定命令的验证器。一个示例是CreateRefreshTokenCommandValidator,它实现了ICommandValidator<CreateRefreshTokenCommand>

根据Simple Injector documentation,在这种情况下应该创建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 个答案:

答案 0 :(得分: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<>));

Original 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方法查找所有非泛型实现,我们将open泛型类型附加到此集合,并使用RegisterAll注册整个集合。

您的第二个选择是将RegisterManyForOpenGenericAppendToCollection混合:

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

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