For a long time now we've been fortunate enough to have the Common Service Locator (CSL) to resolve services from an unknown source. However, there has never been any container-agnostic solution for registering these services in the first place. We've always been faced with the problem of having to couple our composition code to a particular IoC container, and furthermore, be committed to using that container throughout our entire application.
I feel I may be trying to achieve the impossible here, but does anyone have any ideas on how to achieve a Common Service Registry (CSR)?
My original idea was to use MEF to resolve various IContainerIntegrator
s (one class for each container technology), which in turn use MEF to resolve various IXXXContainerBinding
s (one interface for each technology). Users could then develop applications around container bindings, and just drop their bindings into the BIN directory to achieve a plugin architecture. If they wanted to use a new container technology, then they would just have to develop a new IContainerIntegrator
class and accompanying IXXXContainerBinding
, which they would then use to write their own bindings. At application startup the CSR aggregates all of the container instances into a single CSL using a ServiceLocatorAggregator
class.
I have got this working, but am faced with the following problems:
- Any binding which makes calls to the current (incomplete) container is unstable, since the previous registrations may be overridden by subsequent bindings. This includes bindings which need to resolve objects to make registration decisions (i.e. 'bind this if that is present').
- Two bindings may exist which expose the same set of services. However, we want to 'interlace' these registrations. E.g. 'I want services A and C from binding X, and service B and D from binding Y'.
- Containers resolve services from themselves when auto-wiring dependencies of requested services. E.g. 'container.Bind<This>.To<That>()' will automatically inject the implementation with services resolved from 'container' - not from the aggregated service locator.
Please shout at me if I've completely missed the point here, but isn't this the most decoupled solution for dependency management? Wouldn't it be nice? I'm about to embark on a big enterprise project with a plugin architecture. I don't want to commit to a particular IoC container.
(p.s. This question is about container-agnostic composition which supports discovery. Please do not enter a debate on SL vs DI. SL is used in composition, which is why I've referenced it so much here).