.Net Dependency Injection better practice
posted by Paul Hammant
Coming to me via a Reddit "today I learned" link to a 'new' abstraction in the .Net world called the Common Service Locator library
Except its not new, version 1.0 was released September 30th, 2008; It was just new to me.
I did a tweet expressing my extreme dislike, and Robin Clowers
joined in a little to debate me. After a few we retired gracefully to email
to debate some more. My problem was the static accessor to the
container being global meant that this piece was not a facilitator of
Dependency Injection or the older and encompassing Inversion of Control (IoC),
but the antithesis of them. I'm arrogant enough to think that I
kind of know this topic being one of the folks that help start it all.
My claim is that .Net should not have abstraction in the design of 'Common Service
Locator library'. ServiceLocators should be banished when the facilitate static
public access, and more careful thought should be put into
how assemblies can declare their needs and be injected into by the
thing that controls them.
Anyway, with an example in Java
for Robin to look at where the container was completely hidden from
components, but was otherwise a rudimentary DI web-app, Robin went on
to make an equivalent in C# that leveraged separate assemblies and
methods marked internal so that the other assembly could not leverage
the methods designated as hidden to the components. He's blogged about it here which is a better writeup of the achievement than this. Here's the solution in Github. It is a little more complete than mine, as it uses a real DI container - StructureMap (by a former ThoughtWorks colleague). I might prefer Windsor
being that it has a past in Apache's IoC project 'Avalon' as I
do. Robin's example is nice though and I think it should be publicized more, and perhaps held as best practice.
In Java-land it is not exactly squeaky clean. Spring has a static accessor too
(lesser known admittedly). Java-Servlets make it necessary when
you consider which plugin types can take injected dependencies:
| Java servlet component type |
Can be injected? |
Normally a problem in DI web-apps? | PicoContainer's extended Jetty server |
| Servlets | no |
no | yes |
| Filters | no |
no | yes |
| Listeners | no |
no | yes |
| JSP Tags | no |
yup, is a problem | not yet :-( |
It is only tags/taglibs that are problematic, because 99% of DI webapps can be written using the out of the box Spring (etc) supplied servlets/filters/listeners. The components themselves are closer to POJOs and for the most part know nothing of the servlet world.
Robin has left an open question to the .Net community:
I suggest that the issue is that they should not be able to. But then with that claim, I'm back at the start of this debate again.
Some back history
During PicoContainer's initial design, and born perhaps of a prior patronage of Apache's (now cancelled) Avalon project, it was always clear that parent/child containers were the best large-system reality. There are hints to that elsewhere: IIS, Apache-Tomcat (etc) are containers for components that don't facilitate general dependency injection, but could with some rework. Amongst others, the PicoContainer team has reworked Jetty (the other main servlet container for Java) to allow DI of major components, but that's custom to us, and not interoperable with Spring or Guice. See table above.
Aug 20, 2010
