How not to do dependency injection - the static or singleton container
Dependency injection and the use of IoC containers is becoming more and more popular but many development teams do not have the knowledge or experience necessary to fully utilise the power of the IoC container. In the next few posts, we will take a look at the most common mistakes and how to address them. In this post, we are going to talk about the static or singleton container and why this 'pattern' is such a bad idea.
This is part one of a three part series on dependency injection mistakes. All the articles in the series are listed below:
- The Static or Singleton Container
- Configuring the IoC Container in Unit Test Projects
- Using XML over Fluent Configuration
Dependency Injection and the IoC container
Before we begin, let's get something out of the way:
Dependency Injection != Using an IoC container
- You can do dependency injection without the need for an IoC container, or indeed any external tool.
- You can use an IoC container without doing dependency injection and in fact, it is an extremely common (bad) practice.
It is this second point that we are going to talk about in this article. In my experience, by far the most common IoC mistake is to wrap up the container in a public static or singleton class that is referenced throughout the code base. It is important to realise that this is not dependency injection, it is service location which is widely regarded as an anti-pattern. I cannot over-emphasise how important it is to move away from this design and to inject your dependencies from the root of your application. In fact, virtually all other IoC mistakes come about as a direct result of this misunderstanding.
The problem
Let's start from the beginning and very briefly look at life without DI. It is often easy to visualise problems by way of an example, so let us consider the following common architecture:
ASP.NET MVC Controller -> Service Layer -> Repository -> Entity Framework DB Context
If we begin by just looking at a very basic controller that needs to interact with a service layer. Without dependency injection, you would most likely instantiate the service in the controller's constructor, or in each method that the service is being used in.
public class HomeController
{
private readonly IExampleService _service;
public HomeController()
{
_service = new ExampleService();
}
public ActionResult Index()
{
return View(_service.GetSomething());
}
}
So we know that this is bad. Our controller is tightly coupled to the ExampleService and as a result, there is no way to unit test the controller. So how do we address these shortcomings? If you were to search the web for a solution then sooner or later, you would find articles that talk about dependency injection and the use of IoC Containers. Unfortunately, much of what you read on the web about IoC is wrong, so depending on what you read, your design choices may end up being far from ideal.
How to use the IoC container badly - no dependency injection
We can all agree that we really need to remove the fixed dependency on ExampleService from the controller but how we go about this is not so clear. People often seem to completely forget that we are trying to inject dependencies and instead, use the container to retrieve them. Instead of the controller being supplied with the service dependency, they leave it up to the controller to request it.
public class HomeController
{
private readonly IExampleService _service;
public HomeController()
{
_service = Container.Instance.Resolve<IExampleService>();
}
public ActionResult Index()
{
return View(_service.GetSomething());
}
}
This is the birth of the static container. Instead of changing the constructor of the controller to take in the dependency, we are just changing the line where the service is instantiated to resolve it using the container instead. Most (all?) containers themselves are not static but you will find many examples on the web showing how to wrap the container up in a static class or as a singleton. With this done, you can simply call the container from anywhere in your code base. Congratulations, you are now using an IoC container very badly and without dependency injection.
Whilst it can be argued that this approach does reduce coupling between the controller and service and also allows the controller to be unit tested, what we are doing is not dependency injection. Nothing is being injected into the controller - the parameterless constructor gives that away. Instead we are using the container in a way that we want to avoid within our code - as a service locator. So why is this so bad?
Firstly, every class which uses the container in this way has a direct dependency on it, so we are effectively removing one coupling and adding another. Some people might argue that this approach allows you to replace multiple hard-coded dependencies with a single container dependency, effectively reducing coupling but this is missing the point. An IoC container should be there to assist in the building of dependency graphs and as we said previously, you should be able to remove the container and build your graph manually without requiring any changes to the code (other than the root class that starts the application). Using the container as a service locator couldn't be further from this ideal. Without the container, your code will not run at all and any component with a dependency must reference the container.
The other major issue is the fact that it is very unclear what is going on. The beauty of dependency injection is that just by looking at the constructor of a class, you can tell exactly what it depends upon. You then provide these dependencies. If you are unit testing the class, you can manually inject stubs or mocks very simply. Importantly, in your unit test project, you do not need to reference the container at all. The static container approach is the opposite. The caller does not supply anything. Rather, the component goes off and gets what it needs using the container as a service locator. The constructor will typically be empty and without looking thoroughly at the code, it is difficult to determine any dependencies. To unit test a class built in this way, you need to use the container in your unit tests and must configure the container to return fakes for dependencies. Not only is any configuration in unit tests a big red flag indicating that something is not quite right, it also makes it very difficult to use a mocking framework. Modern mocking frameworks such as Moq and RhinoMocks can dramatically improve unit test productivity, but when using the static container, you will most likely end up writing your mocks manually which can be pretty tedious in larger applications.
How to use the IoC container correctly - dependency injection
Although the title of this section states 'How to use the IoC container correctly', if you look at the code below, you will not find a reference to the container at all. This is exactly what we want. 99% of your code base should have no knowledge of your IoC container. It is only the root class or bootstrapper that uses the container and even then, a single resolve call is all that is typically necessary to build your dependency graph and start the application or request.
The code below is very readable and easy to understand. Just a brief look at the constructor tells us that the controller requires an implementation of IExampleService in order to function. If we should want to instantiate the class ourselves, it would be trivial to do so, passing in the constructor dependency. For unit testing, we can inject a mock service and test the interaction between the components. All very simple. No configuration or knowledge of the container necessary. This is dependency injection.
public class HomeController
{
private readonly IExampleService _service;
public HomeController(IExampleService service)
{
_service = service;
}
public ActionResult Index()
{
return View(_service.GetSomething());
}
}
But what about the container? As we have mentioned previously, the important thing about using the container is that you should only interact with it at the entry point of the application. You register all your components with the container and then resolve the root component using the container. All dependencies are satisfied for the root component and all child components - the entire dependency graph. This is all there is to it for a console application, but for website or WCF services, it is a little more complicated. Firstly, whilst we still need to register all the components once at application startup, when resolving, we typically want to resolve once per request. The complication is finding the right place to do the resolve. Fortunately, both WCF and MVC have well-defined points available to hook into the pipeline and packages are readily available to assist with this integration. For MVC3 and Unity integration, you can use the Unity.Mvc3 NuGet Package to get up to speed very quickly.
Any other concerns?
Abstracting the container
People often talk about the need to abstract out the IoC container so you are not directly dependent on one particular product. Whilst in general this philosophy may be a good idea, in the case of an IoC container used correctly, it is unnecessary and unproductive. This is because the IoC container should only be used in a single class at the root of your application. If you want to change your container, you simply change that class - abstractions are totally unnecessary and in fact can often do more harm than good. When you create an abstraction, you will inevitably reduce the functionality available. IoC containers differ quite significantly in functionality, so trying to abstract an interface that will work with multiple containers will mean than features unique to one container cannot be in the interface. It is only if you are mis-using the container that the requirement to abstract it has any validity.
Dynamic component resolution
Another reason cited is the need to resolve components dynamically. It is a common requirement to be able to create an object based on data that can only be know at run-time. A slight variation of this is that if you have a component that is expensive to create, so you may want to delay the instantiation of this object until/if it is required. Both of these scenarios can be easily handled without resorting to accessing the container deep within your code. The answer is factories. Most IoC containers have support for factories and Unity is no exception.
If you need runtime data in order to instantiate a component, you can create a custom factory. When registering the components with Unity, you also register a factory. Looking at the registration code below, the numerous lambda's make the code quite hard to understand, but all we are doing is registering a delegate that takes in a string and returns an IExampleService. You can have any kind of logic you want in this delegate, but for this example, we are just using the string to resolve a named instance of IExampleService. We have therefore registered another IExampleService implementation with the container and named both registrations.
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<IExampleService, ExampleService>("default");
container.RegisterType<IExampleService, AnotherExampleService>("another");
container.RegisterType<Func<string, IExampleService>>(
new InjectionFactory(c =>
new Func<string, IExampleService>(name => c.Resolve<IExampleService>(name))));
container.RegisterControllers();
return container;
}
The controller code does not change dramatically and most importantly, we do not have a reference to the IoC container. We are only using built-in .NET constructs. The constructor changes to take in the delegate that we registered in the previous code snippet. We are hard-coding the service implementation string in this example, but it would typically come from another component which would get the data dynamically. We then call the delegate factory with this string and assign the resultant IExampleService implementation to the private member variable which is then used throughout the controller.
public class HomeController
{
private IExampleService _service;
public HomeController(Func<string, IExampleService> serviceFactory)
{
var exampleServiceImplementation = "default"; // TODO get dynamically
_service = serviceFactory(exampleServiceImplementation);
}
public ActionResult Index()
{
return View(_service.GetSomething());
}
}
If you want to lazy load a component, you can take advantage of Unity's automatic factory support. Just register your component in the usual way, but change any class that depends on the component, to take in a Func
public class HomeController
{
private IExampleService _service;
private readonly Func<IExampleService> _serviceFactory;
public HomeController(Func<IExampleService> serviceFactory)
{
_serviceFactory = serviceFactory;
}
public ActionResult Index()
{
return View(Service.GetSomething());
}
private IExampleService Service
{
get { return _service ?? (_service = _serviceFactory()); }
}
}
Some IoC containers such as AutoFac support the newer Lazy<T> class introduced with .NET 4 which can be used in place of the Func delegate, but unfortunately, right now, out of the box, Unity does not support Lazy.
Conclusion
Dependency injection and using an IoC container are not the same thing and either one can be done without the other. Using an IoC container statically, as a service locator throughout the code base is a common anti-pattern and this post has tried to explain why it should be avoided. Proper dependency injection does not rely on a container and no component should know anything about the container. Instead dependent components are simply passed (injected) via the constructor and at the root of the application, we can either build the dependency graph manually or use the container to resolve the dependency graph automatically. Even if you need lazy loading capabilities or have components that need runtime data to be instantiated, you can still do proper dependency injection without resorting to the evil static or singleton container.
Ironically, this http://microsoftnlayerapp.codeplex.com/ application is riddled with the anti pattern described here. See also http://ayende.com/blog/29697/review-microsoft-n-layer-app-sample-part-iv-ioc-ftw.
I couldn't agree more. I spent a long time fixing up exactly this issue on the last project I was working on. I'm sure we've had this very discussion on more than one occasion!
@Simon - I think we probably have.
If you see this pattern in future projects, then you can point the culprits to this article for some education - I have just done exactly that after reviewing some work that was done for a client by an offshore consultancy.
Thank you for the most understandable explanation of dependency injection that I have found. Finally, I think I am getting somewhere...
"It is an Anti Pattern to user the container directly"
On the other hand, if we abstract the way we resolve the interface, I beleive that is another injection Pattern called the Service Locator Pattern. Both have advantages and disadvantages:
http://martinfowler.com/articles/injection.html
Good luck
@Christian - Martin Fowler's seminal article is a great reference that I would highly recommend reading. He talks about both patterns favourably and concludes that when building application classes, the service locator has a slight edge due to its more straightforward behaviour. However, he then goes on to say that if you are building classes to be used in multiple applications then Dependency Injection is a better choice. His article was written over seven years ago though and since its publication, many influential figures in the .NET and IoC community have spoken about service location in less favourable terms. Here are a few quotes from some names you might recognise:
"So in my opinion using SL is just an excuse for being lazy. The only place where I'd use it (temporarily) is when migrating old, legacy code that can't be easily changed, as an intermediate step." - Krzysztof Kozmic
"...in the ideal world using IoC, the container will never be visible to your app..." - Hamilton Verissimo, aka hammett (founder of the Castle Project)
"Service location is bad…just about 99% of the time..." - Jimmy Bogard
"The .Net IoC community has been very loud about how you should use an IoC ... A good example of that is using ASP.Net MVC Controller Factory, that is the only place in the application that will make use of the container directly." - Ayende Rahien
http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx - Mark Seeman (author of Dependency Injection In .NET)
"Although [StructureMap] works as a service locator, you should avoid using it as one unless it's absolutely necessary, because it couples your services to the kernel itself." - Nate Kohari (author of Ninject)
"Giving components access to the container, storing it in a public static property, or making functions like Resolve() available on a global 'IoC' class defeats the purpose of using dependency injection." - Nicholas Blumhardt (author of AutoFac)
"I detest this pattern and I’ve been eliminating this from my team’s primary product." - Jeremy Miller (author of StructureMap)
I can see a lot of disadvantages with the Service Locator pattern (or anti-pattern) but have a hard time coming up with positives. Do you have any reasons why you might favour Service Location over Dependency Injection?
Hi Paul,
Your article is very enlightening and has persuaded me against my current use of the container as a service locator but I am not clear from your examples on how to retrieve the objects build by the container.
In my current WinForm Application I need to retrieve a view that has dependency when a user clicks a button that loads a form. Would I not use a service locator ( factory ) to retrieve the dependency from the container?
P.S. I am new to Dependency Injection and IoC and didn't even consider to lazy load a component. Thank you for your article.
@Paul
e.g. if you use service locator the class is bound to that locating service process e.g.
_service = Container.Instance.Resolve<IExampleService>();
with di you can declare the dependency in the constructor and let ioc run through all your dependencies at some point in the application entry, this way the class is clean of concrete implementation - this is handled automatically by the bootstrapping setup of ioc check out http://structuremap.net/structuremap/QuickStart.htm
@dvr - Yes, that is the whole point of the article. Maybe you did not read it fully. The gist of the article is that using an IoC container as a service locator should be avoided in favour of proper dependency injection via the constructor.
Hi,
Stumbled upon your article and I like it a lot.Sort of new to IOC .
Everybody seems to say that DI should be done at the root of the application.
Now my doubt. If I have 20 repositories and 20 services and I doing the registration at the root of my app and I am passing this reference all along the chain.
Nothing stops a developer to call the repository from a UI or upper layer when should be done further down the chain.
Do you see what I am trying to say?
If I am calling a WCF Service from my winforms where do I do the injection?
I suppose is in "Program" of my winform calling a bootstrapper class todo the job.
Again nothing stop to call the repository does it?
could you clarify?
@Mark - You are right that nothing stops a developer from doing something silly but as long as your team is adequately trained and there are well defined coding standards, there shouldn't be any reason to worry. Having said that, coding reviews and/or integrating something like NDepend into your builds can be very useful.
If you have a WinForms application calling a WCF service, you have two compositional roots - one for the service and one for the app. In each of these, you will want to configure your IoC container.
WinForms was not designed with IoC in mind so it is not very easy to integrate. You can certainly resolve your main form from program.cs (though you will need to leave the default constructor in order to keep the form designer happy) but what about other forms?
A couple of popular solutions are the MVP pattern or athe Composite UI Application Block
http://msdn.microsoft.com/en-us/library/aa480450.aspx
In WCF, it is not as simple as it could be, but there are many articles details what you need to do. One example is:
http://www.devtrends.co.uk/code-snippets/using_unity_to_resolve_wcf_service_or_allowing_dependency_injection_into_wcf_service_implementation
A teammate of mine asked me if an IOC container could be used by a framework internally. I've always used it in a web app, registering my dependencies in global.asax, and then resolving per request (like you do in controller factory). Is there a way to place the container in your framework, without incurring wiring everything up per request? I can't think of a way except for setting the container in some global property and use that(not ideal).
Great post, gave me some ideas on lazy-loading a dependency. I'm using StructureMap in the project I'm working on.
Instead of your Service property which checks if the _service is initialized, I used Lazy like so:
public class HomeController
{
private Lazy<IExampleService> _service;
public HomeController(Func<IExampleService> serviceFactory)
{
_service = new Lazy(() => serviceFactory());
}
public ActionResult Index()
{
return View(_service.Value.GetSomething());
}
}
Great article concluding all what dependency injection and inversion of control really are about. Thank You.
Hi.
This is amazing article. Just now i understand the correct use of Unity.
I would like to add another concern. How to use correctly Nested Containers?. How can I be sure to use the correct container?
While I think the article has good value I disagree that one should use constructor injection for injecting any arguments that do not belong to (define the) the object.
A constructor should not be a way of passing arguments.
A constructor should just be used to initialize the object with attributes that defines that object. There is no need to "pollute" the signature with references that are not part of the object.
If some other reference is needed later on one has to modify the signature of the constructor when in fact the object itself has not changed.
Instead Property Injection should be used.
In the example that is used the IExampleService should not be part of the HomeController. A HomeController has other attributes that can define it (perhaps location, type, ...). The service is something that the controller uses to complete its task is not part of its signature.
Keeping an object clean is good OO practice.
Excellent indeed. I was just talking about this at work for a new project we're starting, and I was cheering for DI. Still, I made the mistake to use DI from the Data Layer through BLL till the application layer, but there (in the MVC controllers) I did the evil thing of doing the service locator antipattern. I don't know why I used constructor injection in all other layers and then I skipped it for my controllers.
Good candidate for refactoring for tomorrow morning, thank you :)
Good article. I want to provide one counter-example of when you may need to inject the container itself.
First, I do not write web applications, but there is one type of application in which you may need to inject the container itself and does not have necessarily a single application root. What I'm referring to is a modular application, such as described in Microsoft's Prism guidelines. Each module is responsible for registering its types and resolving any instances of objects that it requires. Outside of the module and its initialization, I agree that direct use of the container should be avoided. But for a modular application, each module basically has its own "root". In the module's initialization, just like an application, it would use the container to register and resolve types specific to that loosely-coupled module.
Thanks for the nice explanation and a great article on dependency injection.
However, I am facing one issue while trying to replicate your solution in my project.
that is, I do not find "RegisterController" method for my UnityContainer instance.
@martin Good point about polluting constructor with kind of artificial arguments.
Paul, really interesting article. Good points, good links, good comments. Thank you.
But I find it very bound to MVC specifics where there is the built-in dependency injection root which is the most suitable place for single container configuration. Install and forget.
However in case where there is no such root, say an infrastructure library I'm currently working under (System.Configuration API helper), Service Locator as a static IoC class seems to be suitable. Or please share you thought how to use a container differently.