Autofac Conditional Registration Support
Alex and I have been working on deprecating the ability to update an Autofac container after it’s already been built. There are lots of reasons for this, and if you’re curious about that or have feedback on it, we have a discussion issue set up. You can also see ways to work around the need to update the container in that issue, so check it out.
However, one of the main reasons we’ve heard about why people want to update the container is to handle conditional registrations. For example, “I only want
ComponentB registered in the container if
ComponentA is not registered.”
To that end, in version 4.4.0 we’ve added
IfNotRegistered() extensions to support conditional registration.
OnlyIf() lets you provide a lambda that acts on an
IComponentRegistry. You can check if something is or isn’t registered and have some other registration execute only if the predicate returns
IfNotRegistered() is a convenience method built on
OnlyIf() that allows you to execute a registration if some other service is not registered.
The documentation has been updated to explain how it works including examples but here’s a taste:
var builder = new ContainerBuilder(); // Only ServiceA will be registered. // Note the IfNotRegistered takes the SERVICE TYPE to // check for (the As<T>), NOT the COMPONENT TYPE // (the RegisterType<T>). builder.RegisterType<ServiceA>() .As<IService>(); builder.RegisterType<ServiceB>() .As<IService>() .IfNotRegistered(typeof(IService)); // HandlerA WILL be registered - it's running // BEFORE HandlerB has a chance to be registered // so the IfNotRegistered check won't find it. // // HandlerC will NOT be registered because it // runs AFTER HandlerB. Note it can check for // the type "HandlerB" because HandlerB registered // AsSelf() not just As<IHandler>(). Again, // IfNotRegistered can only check for "As" // types. builder.RegisterType<HandlerA>() .AsSelf() .As<IHandler>() .IfNotRegistered(typeof(HandlerB)); builder.RegisterType<HandlerB>() .AsSelf() .As<IHandler>(); builder.RegisterType<HandlerC>() .AsSelf() .As<IHandler>() .IfNotRegistered(typeof(HandlerB)); // Manager will be registered because both an IService // and HandlerB are registered. The OnlyIf predicate // can allow a lot more flexibility. builder.RegisterType<Manager>() .As<IManager>() .OnlyIf(reg => reg.IsRegistered(new TypedService(typeof(IService))) && reg.IsRegistered(new TypedService(typeof(HandlerB)))); // This is when the conditionals actually run. Again, // they run in the order the registrations were added // to the ContainerBuilder. var container = builder.Build();