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:

Dependency Injection and the IoC container

Before we begin, let's get something out of the way:

Dependency Injection != Using an IoC container

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 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 rather than a T. There is no need to register the factory with Unity if it is a simple Func and does not require additional data.

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.

Useful or Interesting?

If you liked the article, I would really appreciate it if you could share it with your Twitter followers.

Share on Twitter

Comments

Avatar for Eddie Groves Eddie Groves wrote on 13/07/2011

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.

Avatar for Simon Rigby Simon Rigby wrote on 14/07/2011

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!

Avatar for Paul Hiles Paul Hiles wrote on 16/07/2011

@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.

Avatar for Sarah Campion Sarah Campion wrote on 19/07/2011

Thank you for the most understandable explanation of dependency injection that I have found. Finally, I think I am getting somewhere...

Avatar for Christian Christian wrote on 26/07/2011

"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

Avatar for Paul Hiles Paul Hiles wrote on 27/07/2011

@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?

Avatar for Chris Bishop Chris Bishop wrote on 02/08/2011

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.

Avatar for dvr dvr wrote on 16/11/2011

@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

Avatar for Paul Hiles Paul Hiles wrote on 17/11/2011

@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.

Avatar for Mark Mark wrote on 02/01/2012

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?

Avatar for Paul Hiles Paul Hiles wrote on 03/01/2012

@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

Avatar for A'braham Barakhyahu A'braham Barakhyahu wrote on 07/03/2012

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).

Avatar for Tsahi Tsahi wrote on 14/03/2012

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());
}
}

Avatar for Per Dahl Per Dahl wrote on 24/03/2012

Great article concluding all what dependency injection and inversion of control really are about. Thank You.

Avatar for Ramiro Bautista Ramiro Bautista wrote on 20/07/2012

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?

Avatar for martin martin wrote on 15/08/2012

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.

Avatar for Matteo Matteo wrote on 09/10/2012

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 :)

Avatar for Alan Alan wrote on 22/01/2013

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.

Avatar for Nirman Doshi Nirman Doshi wrote on 27/02/2013

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.

Avatar for Alexander M. Batishchev Alexander M. Batishchev wrote on 15/03/2013

@martin Good point about polluting constructor with kind of artificial arguments.

Avatar for Alexander M. Batishchev Alexander M. Batishchev wrote on 15/03/2013

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.

Comments are now closed for this article.