Using a simple injector with the command template described here . Most teams have companion classes that implement seamless validation AbstractValidator<TCommand>, which means they also implement FV IValidator<TCommand>. However, it does not always make sense to have a validator implementation for each team.
As far as I can tell, the implementation of the command decorator cannot accept IValidator<TCommand>arg as the constructor if everyone ICommandHandler<TCommand>does not have the corresponding FV. IValidator<TCommand>. I tried the following:
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;
});
Unit tests that run Container.Verify()once pass. Unit tests that run Container.Verify()more than once exit from the InvalidOperationExceptionsecond call:
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, . , , , unit test ( , ).
simpleinjector CommandHandler<TCommand> FluentValidationCommandDecorator<TCommand>, , IValidator<TCommand>?