有没有办法有条件地将类型注册为 .NET 依赖注入的回退?
Is there a way to conditionally register types as fallback with .NET dependency injection?
我们目前使用 SimpleInjector 作为我们的 DI 容器,通过使用 ICommand
and IQuery<TResult>
and ICommandHandler<TCommand>
and IQueryHandler<TQuery, TResult>
来实现命令查询分离 (CQS) 模式接口。
我们也使用装饰器模式来进行面向方面的编程。对于我们的装饰器之一,我们使用 FluentValidation 来执行特定命令或查询的验证逻辑。
使用 SimpleInjector,可以有条件地注册类型。当我们有一个 not 没有相应验证器的命令或查询时,这对我们的 FluentValidation 装饰器很有用。然后我们使用 NullValidator<T>
作为后备,什么也不做。 SimpleInjector documentation 中描述了这种情况,对于 FluentValidation 情况看起来像这样:
public class NullValidator<T> : AbstractValidator<T>
{
}
container.RegisterConditional(
typeof(IValidator<>),
typeof(NullValidator<>),
c => !c.Handled); // Applied if no other validator matches
NullValidator<T>
是必需的,因为总是应用装饰器并且总是注入 IValidator<T>
。对于不存在的特定验证器,使用 NullValidator<T>
。这是命令的 FluentValidation 装饰器的构造函数:
public FluentValidationCommandHandlerDecorator(
IValidator<TCommand> validator,
ICommandHandler<TCommand> decoratee)
{
this.validator = validator ?? throw new ArgumentNullException(nameof(validator));
this.decoratee = decoratee ?? throw new ArgumentNullException(nameof(decoratee));
}
这工作得很好,但现在我们正在评估删除对 SimpleInjector 的依赖,并使用 .NET 依赖注入(IServiceCollection
来自 Microsoft.Extensions.DependencyInjection
)结合 Scrutor 进行注册我们的 ICommandHandler<T>
和 IQueryHandler<TQuery, TResult>
实现以及我们的装饰器。
是否有任何方法可以执行类似的条件注册逻辑或后备机制,如 .NET DI 框架中支持的 SimpleInjector?
我设法通过在 FluentValidationCommandHandlerDecorator
装饰器中注入一个 IEnumerable<IValidator<T>>
而不是一个 IValidator<T>
实例来解决这个问题。在那种情况下,我根本不需要 NullValidator<T>
,如果没有可用于特定命令或查询的验证器,则会注入一个空集合。
必须更改 SimpleInjector 以注册 IValidator<T>
个实例的集合:
container.Collection.Register(typeof(IValidator<>), assemblies);
Microsoft.Extensions.DependencyInjection
DI 容器支持注入 IEnumerable<IValidator<T>>
开箱即用,无需在注册中更改任何内容。
我们目前使用 SimpleInjector 作为我们的 DI 容器,通过使用 ICommand
and IQuery<TResult>
and ICommandHandler<TCommand>
and IQueryHandler<TQuery, TResult>
来实现命令查询分离 (CQS) 模式接口。
我们也使用装饰器模式来进行面向方面的编程。对于我们的装饰器之一,我们使用 FluentValidation 来执行特定命令或查询的验证逻辑。
使用 SimpleInjector,可以有条件地注册类型。当我们有一个 not 没有相应验证器的命令或查询时,这对我们的 FluentValidation 装饰器很有用。然后我们使用 NullValidator<T>
作为后备,什么也不做。 SimpleInjector documentation 中描述了这种情况,对于 FluentValidation 情况看起来像这样:
public class NullValidator<T> : AbstractValidator<T>
{
}
container.RegisterConditional(
typeof(IValidator<>),
typeof(NullValidator<>),
c => !c.Handled); // Applied if no other validator matches
NullValidator<T>
是必需的,因为总是应用装饰器并且总是注入 IValidator<T>
。对于不存在的特定验证器,使用 NullValidator<T>
。这是命令的 FluentValidation 装饰器的构造函数:
public FluentValidationCommandHandlerDecorator(
IValidator<TCommand> validator,
ICommandHandler<TCommand> decoratee)
{
this.validator = validator ?? throw new ArgumentNullException(nameof(validator));
this.decoratee = decoratee ?? throw new ArgumentNullException(nameof(decoratee));
}
这工作得很好,但现在我们正在评估删除对 SimpleInjector 的依赖,并使用 .NET 依赖注入(IServiceCollection
来自 Microsoft.Extensions.DependencyInjection
)结合 Scrutor 进行注册我们的 ICommandHandler<T>
和 IQueryHandler<TQuery, TResult>
实现以及我们的装饰器。
是否有任何方法可以执行类似的条件注册逻辑或后备机制,如 .NET DI 框架中支持的 SimpleInjector?
我设法通过在 FluentValidationCommandHandlerDecorator
装饰器中注入一个 IEnumerable<IValidator<T>>
而不是一个 IValidator<T>
实例来解决这个问题。在那种情况下,我根本不需要 NullValidator<T>
,如果没有可用于特定命令或查询的验证器,则会注入一个空集合。
必须更改 SimpleInjector 以注册 IValidator<T>
个实例的集合:
container.Collection.Register(typeof(IValidator<>), assemblies);
Microsoft.Extensions.DependencyInjection
DI 容器支持注入 IEnumerable<IValidator<T>>
开箱即用,无需在注册中更改任何内容。