ipjohnson / Grace

Grace is a feature rich dependency injection container library
MIT License
336 stars 33 forks source link

Conditional resolution of decorators #155

Closed davidkeaveny closed 6 years ago

davidkeaveny commented 6 years ago

I have the following interface:

public interface ICommandHandler<TCommand>
{
    void Handle(TCommand command);
}

which I then want to decorate with a validating decorator:

public class ValidatingDecorator<TCommand> : ICommandHandler<TCommand>
{
    public ValidatingDecorator(IValidator<TCommand> validator, ICommandHandler<TCommand> innerHandler)
    {
    }

    public void Handle(TCommand command)
    {
        if (!_validator.IsValid(command))
        {
            throw new InvalidOperationException()
        }

        _innerHandler.handle(command);
    }
}

At the moment, Grace throws a LocateException if it cannot resolve the dependency - how can I make it either a) return null (which I then handle internally) or b) return a default implementation?

ipjohnson commented 6 years ago

@davidkeaveny I'm assuming you mean the IValidator<TCommand> is not always registered and that's where you are running into the issue?

You can either explicitly mark the parameter as not required when it's registered using c.ExportDecorator<T>().WithCtorParam<TParam>().IsRequired(false) or you can implicitly specify it by making the parameter optional (i.e. = null).

As for registering a default implementation you could register an open generic version of IValidator<T> that always returns true. Closed implementations are used before open implementations (provided they are in the same scope).

davidkeaveny commented 6 years ago

How does the usage of .WithCtorParam() work with an open generic registration? If my current registration code is:

c.ExportDecorator(typeof(ValidatingDecorator<>)).As(typeof(ICommandHandler<>));
ipjohnson commented 6 years ago

I think this should do it.

c.ExportDecorator(typeof(ValidatingDecorator<>)).As(typeof(ICommandHandler<>)).WithCtorParam<object>().Named("validator").IsRequired(false);
ipjohnson commented 6 years ago

Can I close this out?

davidkeaveny commented 6 years ago

Sorry, yes this can be closed.