Is there an equivalent in .NET DI to SimpleInjector's RegisterConditional?

Viewed 23

I'm trying to go as native .NET as possible with a project I'm working on but the reference project I'm migrating has some Simple Injector registrations. Here's a line I'm stuck on

container.Register<IValidator<Foo>, FooValidator>();
container.Register<IValidator<Bar>, BarValidator>();

container.RegisterConditional(
    typeof(IValidator<>),
    typeof(ValidateNothingDecorator<>),
    LifeStyle.Singleton,
    c => !c.Handled);

This is from the Simple Injector documentation and I'm wondering if there's an equivalent way to do this on the built in .NET 6 IServiceCollection?

1 Answers

Although there is no equivalent for RegisterConditional in MS.DI, and I'd say that in many cases you're out of luck, in this particular case you are likely using the ValidateNothingDecorator<T> as a fallback in case no explicit (non-generic) registration exists. This can be done as follows in MS.DI:

services.AddTransient<IValidator<Foo>, FooValidator>();
services.AddTransient<IValidator<Bar>, BarValidator>();

// Register open-generic fallback
services.AddSingleton(typeof(IValidator<>), typeof(ValidateNothingDecorator<>));

In MS.DI a registration for an open-generic type always functions as fallback; in other words, if there exists an explicit registration for a specific closed version (e.g. IValidator<Foo>) of the given open-generic interface (e.g. IValidator<>), the closed version is selected.

This is not how it works with Simple Injector. In Simple Injector you explicitly have to specify the conditional registration is the fallback using the !c.Handled lambda. This design is chosen explicitly to make the registration process less implicit and less error prone. Using this design, it allows Simple Injector to validate the correctness of the registrations, because Simple Injector does not implicitly chose from multiple applicable registrations; it forces to you specify what you meant.

Related