Is this the right way for RegisterDecorator when some types have no implementation?

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>?

+3
1

, . , , RegisterOpenGeneric:

container.RegisterOpenGeneric(typeof(IValidator<>), 
    typeof(NullValidator<>));

NullValidator<T>, IValidator<T> / .

, () IValidator<T>, NullValidator<T>. , RegisterManyForOpenGeneric, .

NullValidator<T> ( , ), , singleton:

container.RegisterSingleOpenGeneric(typeof(IValidator<>), 
    typeof(NullValidator<>));

:

+2

All Articles