Inversion of Control – An Introduction with Examples in .NET

Lately I’ve been giving a couple of presentations on the subject of automated testing of websites. According to myself and the feedback I’ve gotten one of the most important parts of the presentations has been the part about Inversion of Control. While I’m no expert on the subject I still thought I’d write down that part of the presentation in an introduction to Inversion of Control, using Dependency Injection and Service Locator along with some examples in .NET (C# to be precise).

What is Inversion of Control?

According to Wikipedia “Inversion of Control, or IoC, is an abstract principle describing an aspect of some software architecture designs in which the flow of control of a system is inverted in comparison to procedural programming”. The latter part of that quote is interesting. According to it Inversion of Control is a way to invert the flow of control in comparison to procedural programming. What that means is that in procedural programming a chunk of code that uses, or consumes, another chunk of code is in control of the process. It knows exactly what piece of code, what method in what class, it uses. And in doing so it is also quite likely that it knows about some implementation details in the code it uses.

An example

One example of such a scenario and of such a dependency is when a class, illustrated as X below, uses another class Y.

Inversion of control - before

The consumer, X, needs the consumed class, Y, to accomplish something. That’s all good and natural, but does X really need to know that it uses Y? Isn’t it enough that X knows that it uses something that has the behavior, the methods, properties etc, of Y without knowing who actually implements the behavior? By extracting an abstract definition of the behavior used by X in Y, illustrated as I below, and letting the consumer X use an instance of that instead of of Y it can continue to do what it does without having to know the specifics about Y.

Inversion of control - after

In the illustration above Y implements I and X uses an instance of I. While it’s quite possible that X still uses Y what’s interesting is that X doesn’t know that. It just knows that it uses something that implements I. That could be Y, but it could also be A, B or C given that they implement I. Of course this discussion is rather abstract at the moment, but we’ll get to how to implement this in a second using either Dependency Injection or Service Locator. For now, let’s just assume that we can and that we can change what implementation of I X uses at runtime. What benefits can we get from that?

Benefits of Inversion of Control

Well, first of all X is not dependent on Y anymore and it’s therefore less likely that we’ll have to make changes to X when we make changes in Y as we’re less likely to write code in X that relies on implementation details in Y. Furthermore X is now much more flexible as we can change which implementation of I it uses without changing anything in X. Perhaps Y is a component for sending e-mails and we want X, who used to send e-mails, to start sending tweets instead using Z who also implements I. Since X no longer relies specifically on Y but on something that implements I we don’t have to modify anything in X.

Another benefit of inversion of control is also that we can isolate our code when creating unit tests. Suppose, as before, that X used Y to send messages which Y did in the form of e-mails using an SMTP-server. When creating unit test, which should only test a single unit of code, we want to be able to test the logic in X without having to care about the component that sends messages, and we most definitely don’t want our tests to fail because Y doesn’t have access to an SMTP server. Having used inversion of control X doesn’t rely on Y anymore but on an implementation of I that just happens to be Y. That means that we, in the setup phase of our tests, can change it so that X uses a different implementation of I, such as a mock object which doesn’t send any messages at all, and which also allows us to check that X has used it in a correct way.

Applying Inversion of Control – A sample scenario

Enough with the X and the Y and I! Let’s look at a more concrete scenario. We have a class named OrderService which is used for processing orders. It has a method named AcceptOrder which receives an Order object, validates that it is valid according to the business rules (it may for instance check that the order’s shipping address is a valid address and that there are enough items in stock) and then, given that the order is valid, saves it to a database using another class named OrderDatabase.

Inversion of control example - before

The code for OrderService looks like this:

public class OrderService
{
    public void AcceptOrder(Order order)
    {
        //Domain logic such as validation

        new OrderDatabase().SaveOrder(order);
    }
}

Notice line seven above where AcceptOrder creates a new instance of the OrderDatabase class and then saves the order using it’s SaveOrder method. This might not be the most realistic scenario. In the real world SaveOrder could be static, making line seven in the example look like this:

OrderDatabase.SaveOrder(order);

Or there might a singleton implementation of OrderDatabase making line seven look like this:

OrderDatabase.Instance.SaveOrder(order);

Either way it doesn’t matter. What matters is that AcceptOrder relies on OrderDatabase which is something very concrete.

How OrderDatabase is implemented isn’t very important as long as we realize that relying on it is inflexible and bad for testability. For the sake of this example let’s assume it’s SaveOrder method looks like this:

public void SaveOrder(Order order)
{
    throw new ApplicationException("I need a database to work");
}
This will make it very hard to test the business logic in OrderService’s AcceptOrder method since it will call the SaveOrder method which in turn throws an exception. To fix this we apply Inversion of Control by creating an abstract definition of the behavior in OrderDatabase that OrderService needs in the form of the interface IOrderSaver and making AcceptOrder use an instance of IOrderSaver instead of an instance of OrderDatabase.

 

Inversion of control example - after

OrderService no longer knows about the OrderDatabase class. It just uses an instance of the IOrderSaver interface of which OrderDatabase is one of possibly many implementation. In fact we could easily change it so that OrderService instead uses a class that saves orders to XML files instead, without changing a single line of code in OrderService. Or to a class that still saves to a database but that has been extended with logging. Or to a composite that saves both to a database and to an XML file. Or to…

Inversion of control - benefits

That’s all good, but how does OrderService get this instance of IOrderSaver you ask? There would be little point in using the IOrderSaver interface if OrderService still had to know how to instantiate a concrete implementation of it, so we need a way for OrderService to get an instance of IOrderSaver at runtime without knowing about any concrete implementations. There are a couple of ways to do that. Let’s begin by looking at Dependency Injection.

Dependency Injection

Using Dependency Injection we inject an instance of IOrderSaver into OrderService when we use it. This could either be done using constructor injection, where we supply the instance to OrderService’s constructor, or property injection where we supply it to OrderService after it has been instantiated by setting a property on it. In the diagram below I’ve tried to illustrate constructor injection.

Dependency Injection

Notice how OrderService has a constructor which requires an instance of IOrderSaver as a parameter. In code this could be implemented like this:

public class OrderService
{
    private IOrderSaver orderSaver;

    public OrderService(IOrderSaver orderSaver)
    {
        this.orderSaver = orderSaver;
    }

    public void AcceptOrder(Order order)
    {
        //Domain logic such as validation

        orderSaver.SaveOrder(order);
    }
}

As you can see in the example code above OrderService’s constructor requires an instance of IOrderSaver which it stores in a field. When invoked the AcceptOrder method uses this injected instance to save the order.

Should we want to be able to instantiate OrderService without supplying an IOrderSaver there is of course nothing stopping us from creating another constructor which sets the orderSaver field to a default implementation.

public OrderService()
{
    this.orderSaver = new OrderDatabase();
}

While this means that OrderService still knows about which implementation of IOrderSaver it uses when instantiated with this constructor we are still able to change what implementation it uses using the other constructor, for instance when we are creating unit tests. I’m not saying this is a good idea, but it is possible and definitely better than not being able to change how OrderService saves orders at all.

Service Locator

While I think Dependency Injection is superior in just about any situation there is also another way to implement Inversion of Control, using a Service Locator.

Inversion of control - using a service Locator

In the diagram above OrderService doesn’t know about OrderDatabase but it does know about the concrete class OrderSaverFactory (our Service Locator) which in turn knows about OrderDatabase. When AcceptOrder is invoked it will ask OrderSaverFactory for an instance of IOrderSaver which will supply one based on how we have configured it.

Using this approach OrderService could be implemented like this:

public class OrderService
{
    public void AcceptOrder(Order order)
    {
        //Domain logic such as validation

        OrderSaverFactory.GetOrderSaver().SaveOrder(order);
    }
}

A simple implementation of OrderSaverFactory would be to have it supply an instance of a default implementation of IOrderSaver unless we specifically tell it to supply another instance, like this:

public class OrderSaverFactory
{
    public static IOrderSaver OrderSaver { get; set; }

    public static IOrderSaver GetOrderSaver()
    {
        if (OrderSaver == null)
            OrderSaver = new OrderDatabase();

        return OrderSaver;
    }
}

I find the Service Locator approach to be much more messy than Dependency Injection, but there might be a few situations where Dependency Injection may be impractical and then it’s good to still be able to apply Inversion of Control by using Service Locator.

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Comments

  1. Cagdas's avatar

    Cagdas 1 years ago

    Nice post. Simple and good explanation. Thanks

  2. Stefan Forsberg's avatar

    Stefan Forsberg 1 years ago

    Haha, I'm just in the process of writing a blog post at EpiServer World on how to use StrucutreMap to do IoC with EPiAbstractions.

    Mind if I link to this post since you've done a nice job of explaining what IoC is here?

  3. Joel Abrahamsson's avatar

    Joel Abrahamsson 1 years ago

    Not at all. Looking forward to that post.

  4. L. Niedzielski's avatar

    L. Niedzielski 1 years ago

    I was searching for short and clear explanation of the topic. Good job !

  5. Bhuvanesh's avatar

    Bhuvanesh 1 years ago

    Very good article...

    Thanks...

  6. jayee's avatar

    jayee 1 years ago

    Awesome I spent about 1 hour in searching nice explanation and to understand what is IOC and dependency Injection.

    This post made clear all my doubts. It's too good

  7. Karoline Klever's avatar

    Karoline Klever 1 years ago

    I'm amazed by your ability to make any topic seem simple! Thanks for a great post :)

  8. Joel Abrahamsson's avatar

    Joel Abrahamsson 1 years ago

    Thanks Karoline, really glad you liked it!

  9. Gaurav Lall's avatar

    Gaurav Lall 1 years ago

    You made IOC look so simple, Tons of thanks

  10. Ranjit J. Vaity's avatar

    Ranjit J. Vaity 1 years ago

    Hi Joel,

    Nice explanation IOC liked it....

    /Ranjit J. Vaity

  11. Chaitanya's avatar

    Chaitanya 11 months ago

    Great job. Its a good example of IOC.

  12. Jeffrey Rudesyle's avatar

    Jeffrey Rudesyle 11 months ago

    Incredible job explaining this in very simple terms with simple examples.

  13. Sathish's avatar

    Sathish 9 months ago

    Nice Job mate! Really nice and simple. Keep the good job!!!

  14. satish's avatar

    satish 9 months ago

    Hey..It was a great blog post.. But still service locator pattern is an antipattern so may be you have to correct that part of it

  15. Rags's avatar

    Rags 8 months ago

    Good One. Nice and Simple. i have been looking ways to explain the Inversion of control concept to developers in simpler way and this does the job . Great Mate.

  16. Hari's avatar

    Hari 6 months ago

    Very nice!!!!!!!!!

  17. jaszczda's avatar

    jaszczda 6 months ago

    Very helpful(and clear) introduction. Thank You.

  18. Raj's avatar

    Raj 6 months ago

    Solid article dude!

  19. Sasireka's avatar

    Sasireka 5 months ago

    Very good article!. It is a good example of IOC. Thank you so much.

  20. Ramesh's avatar

    Ramesh 5 months ago

    Great article.

  21. Anuj Kumar Sahu's avatar

    Anuj Kumar Sahu 5 months ago

    Very Nice Article !

  22. Aarti's avatar

    Aarti 5 months ago

    Very good article. Cleared a lot of doubts. I am glad I found your blog.

  23. crisgomez's avatar

    crisgomez 5 months ago

    Why are you using static for OrderSaver and GetOrderSaver under OrderSaverFactory class?

  24. Mahesh Kurup's avatar

    Mahesh Kurup 4 months ago

    Simple and Clear.
    Not only IoC, but thanks for explaining Dependency injection and Service Locator.
    Keep up the good work.

  25. Aritra Mukherjee's avatar

    Aritra Mukherjee 1 months ago

    Excellent post....

  26. Jairo's avatar

    Jairo 1 months ago

    Even I knew some things about the topic already, your post helped me to reinforce that knowledge, thanks a lot Joel, I couldn`t find it more simple than that!

Follow me on Twitter

  1. @chraas You might want to use it for complex parts of the site and not use it for simple rendering pages. 2 days ago
  2. @chraas In theory more SOLID, but I'm not sure it's worth the price. 2 days ago
  3. @chraas Be warned that you're introducing one big chunk of complexity with EPiMVP :) 2 days ago
follow me

Latest comments

  1. Berra S wrote "Read your post at http://joelabrahamsson.com/entry/using-xfo..." on PageData objects not returned as typed when using Page Type Builder and FindPagesWithCriteria
  2. Linus wrote "1 up for behaviour being as close as expected as possible!" on A common problem with Page Type Builder and UniqueValuePerLanguage set to false
  3. Joel Abrahamsson wrote "Hi Hans, Could it be that you previously didn't have Page..." on Page Type Builder 2.0 released

About this site

This blog is built with EPiServer Community, EPiServer CMS, ASP.NET MVC and a bunch of other great products. The source code is available for download at the projects page, where you also can read more about this site and my other projects.

read more