使用带有此处描述的命令模式的简单注入器。大多数命令都有实现流利验证的伴随类AbstractValidator<TCommand>
,这意味着它们也实现了 FV IValidator<TCommand>
。然而,对每个命令都有一个验证器实现并不总是有意义的。
据我所知,命令装饰器实现不能IValidator<TCommand>
作为构造函数 arg,除非每个ICommandHandler<TCommand>
都有相应的 FV。IValidator<TCommand>
. 我尝试了以下方法:
public class FluentValidationCommandDecorator<TCommand>
: IHandleCommands<TCommand>
{
public FluentValidationCommandDecorator(IHandleCommands<TCommand> decorated
, IValidator<TCommand> validator
)
{
_decorated = decorated;
_validator = validator;
}
...
}
...
container.RegisterManyForOpenGeneric(typeof(IValidator<>), assemblies);
container.RegisterDecorator(typeof(IHandleCommands<>),
typeof(FluentValidationCommandDecorator<>),
context =>
{
var validatorType =
typeof (IValidator<>).MakeGenericType(
context.ServiceType.GetGenericArguments());
if (container.GetRegistration(validatorType) == null)
return false;
return true;
});
运行Container.Verify()
一次的单元测试通过。Container.Verify()
多次运行的单元测试InvalidOperationException
在第二次调用时失败:
The configuration is invalid. Creating the instance for type
IValidator<SomeCommandThatHasNoValidatorImplementation> failed. Object reference
not set to an instance of an object.
以下工作,以Container
为参数:
public class FluentValidationCommandDecorator<TCommand>
: IHandleCommands<TCommand>
{
private readonly IHandleCommands<TCommand> _decorated;
private readonly Container _container;
public FluentValidationCommandDecorator(Container container
, IHandleCommands<TCommand> decorated
)
{
_container = container;
_decorated = decorated;
}
public void Handle(TCommand command)
{
IValidator<TCommand> validator = null;
if (_container.GetRegistration(typeof(IValidator<TCommand>)) != null)
validator = _container.GetInstance<IValidator<TCommand>>();
if (validator != null) validator.ValidateAndThrow(command);
_decorated.Handle(command);
}
}
...
container.RegisterManyForOpenGeneric(typeof(IValidator<>), assemblies);
container.RegisterDecorator(typeof(IHandleCommands<>),
typeof(FluentValidationCommandDecorator<>));
如果这个类不需要依赖 Simple Injector,我可以将它移到域项目中。该域已经依赖于 FluentValidation.net,因此可以对域有效性进行单元测试。我认为这个装饰器属于域,但它和它的单元测试项目都不依赖于 simpleinjector(或者应该必须,因为域不是组合根)。
有没有办法告诉 simpleinjector 只CommandHandler<TCommand>
用 a 装饰一个实例,FluentValidationCommandDecorator<TCommand>
如果有注册的实现IValidator<TCommand>
?