I am using Autofac to handle dependency injection in my application. In order not to have to do every single registration explicitly, I first use RegisterAssemblyTypes().AsImplementedInterfaces() and then only take care of those that need to be specially configured.
I have an interface called IToolStripPopulator that has a few different implementations, several of which are in use, but some aren’t anymore (as I’m trying to work SOLIDly and adhere to OCP, I am usually not changing them if I need different functionality, but rather leave them alone and create new ones that do what I need now). For that reason I need to overwrite the automatic registration for the interface, in two ways:
- One implementation is to be injected into my main logic and acts as a decorator for a few of the others. I naturally want this to be registered via
As<IToolStripPopulator>()and be done with it as this is the implementation my application’s functionality currently depends on. - Those other implementations are the “inner” populators only to be used within that decorator class. To inject them, there are two ways:
- Explicitly wiring up the constructor for the outer implementation with the specific types; this is not very nice, also because that constructor would have to take the exact number of inner populators I am using right now, which is not OCP compliant.
- Have the outer implementation take an
IEnumerable<IToolStripPopulator>; this is what I’d like to do, but it’s also where I’m stuck.
I can’t let Autofac resolve that IEnumerable on its own, because it would just resolve all implementations of the interface, even those that I’m not using anymore as well as the “outer” that I don’t want in there (and which would probably cause an endless loop during resolution).
So what I’d like to do is this:
// the inner populators
builder.RegisterType<BrowsersMenuPopulator>().Named<IToolStripPopulator>("inner");
builder.RegisterType<ThreadsafeConnectionMenuPopulator>().Named<IToolStripPopulator>("inner");
// the decorator implementation
builder.RegisterType<BrowserAndConnectionMenuPopulator>().As<IToolStripPopulator>().WithParameter( ? );
But there is no way to actually access the existing registrations at that point.
….and here I tried just one more thing which I didn’t actually expect to work, but it did.
does not, as I would have expected, try to resolve an
IEnumerable<IToolStripPopulator>registration named “inner”, but anIEnumerableofIToolStripPopulatorregistrations named “inner” – exactly as I need it.This will then correctly be resolved and injected into the decorator implementation just from having that registered
As<IToolStripPopulator>()with no further configuration.From a formal aspect I would actually have preferred being able to state the name by which to resolve directly with the decorator registration because that would be more intuitive and flexible (what if I need to resolve several
IEnumerable<IToolStripPopulator>?), but in many cases this should be enough.@codinghorror’s concept of “rubber duck problem solving” rules my every workday….