Inversion of control, dependency injection, service locator and so on. Feeling lost?

Lately, I have been bombarded with talk about inversion of control (IoC), dependency injection (DI) and service locators. Unfortunately, I have also heard a lot of odd comments that doesn’t really make sense. But I think that is because people are having trouble separating the different words and understanding what they actually mean.  So I thought I would try to explain the different things as I have understood them. And do so using a simple understandable language, instead of the often overly complex way that a lot of other people use.

The first thing to understand, is the idea of dependency inversion. So…what is dependency inversion? Well… The idea behind it is just what the expression says, to inverse the dependencies. But what does that mean? Well…a lot of the objects that we use have dependencies on other objects.

If object A depends on object B to perform it’s task, that means that if object C wants to use object A, it will also be dependant on object B. This makes everything very inflexible and makes it harder to reuse class.

A simple example is this logging scenario. Say that one of the objects we use that needs to log what it is doing. It could look something like this

public class MyClass
{
Logger _logger;

public MyClass()
{
_logger = new Logger();
}
public void Execute()
{

_logger.LogEvent("My Event");
}
}

The problem with above code is that we have now coupled the MyClass to the Logger class. And why is this a problem? Well, there are a few reasons why this is a problem.

It for example means that any object that uses the MyClass class, is also dependant on the Logger class. That means that the MyClass object cannot be used in more than very specific situations. If my application needs to log in some other way, I cannot use the MyClass class.

One situation where we would probably like to change the logger would be while unit testing the MyClass class. Why? Well, if my unit test tests the Execute method, it might fail if there is a problem in the Logger class. So I am actually testing more than just the Execute() method. I am testing the LogEvent method as well. And if I am unlucky, the Logger class causes my test to fail, even if the Execute() method is actually correct. And what happens if the logger class in turn has even more dependencies. Maybe it uses another class to log the message to the database. As you can see, this dependency can cause us a lot of grief during for example testing.

And what happens if I decide that I do want to use the MyClass class, but need to change the logging process. Maybe I want to stop logging to the database and instead log to disk or maybe to a command prompt. Well…that becomes really hard. In the previous code, the only way to solve it, is to either create a new Logger class and update every single piece of code that uses logging, or change the implementation of the Logger class. Either way, it is a pain in the butt and about as flexible as a brick.

This is where inversion of control or IoC comes into play. However, this is where it gets a bit confusing. I have heard a bunch of people talking about how important it is to use IoC and how we should use a technique called dependency injection to get that IoC. However, DI is just a form of IoC. They are not two different things. IoC is a very generic term that can be used to describe a lot of different things, and the type of IoC that we are talking about so much about right now needs a name of its own. You can read more about it on Martin Fowler’s site. The other type of IoC that we use is Service Locator. I will talk more about this later, but thought I would mention here as it is talked about by Mr. Fowler.

By using DI, we can inverse this dependency on the Logger class and make the MyClass class easier to reuse. Instead of having the MyClass class instantiate a Logger class for logging and making it, and any object using the MyClass, dependant on the Logger class, we can make the MyClass depend on the parent class to pass in the logger to use. This is basically what dependency injection means. To get any dependencies injected into the class, making it more flexible adn testable and so on. The DI  is often done using a constructor parameter (constructor injection) or via a property (property injection). The dependency is also abstracted into an interface to make it less coupled. Like this:

public class MyClass
{
ILogger _logger;

public MyClass(ILogger logger)
{
_logger = logger;
}

public void Execute()
{
_logger.LogEvent("My Event");
}
}

By getting the logger injected as a constructor parameter, the dependency has been inversed and the MyClass class is now depending on someone else to pass in the dependency instead of the other way around. And to decouple it and make it more flexible, the Logger class has been replaced by an ILogger interface.

However, this becomes really tiresome quickly. Because when you get hierarchies of objects, there are a lot of dependencies that needs to be passed around. Not to mention the fact that you will have to pass in every single dependency needed for every object in the hierarchy when creating the the root object. The constructor for that root object will take in a gazillion parameters to satisfy all the objects in the hierarchy and then pass them on as it instantiates the children. To solve this, we have IoC Containers. IoC Containers help us with this. It is a way for us to register all our dependencies in one place. The container is then used to get hold of instances of classes in our code.

There are a lot of IoC containers out there, and it isn’t too hard to build a simple one on your own. Some of the more popular ones are Ninject, StructureMap, AutoFac, Castle Windsor, Spring.NET and Unity. Which you choose is irrelevant. They all do more or less the same thing, with some small differences. Just grab one that you like…

The way that they work is not that complicated. You register your dependencies with the container. Registration is done by passing the container an interface that the dependency implements, and the concrete class to use when that interface is requested. You can also define if it is a singleton and a few other things. You then use the container to get hold of instances of your dependencies. You call the container and tell it that you need for example an ILogger, and it returns an instance of the class you have registered as the class responsible for implementing this interface.

That is the simple part, the interesting and cool part is that it also solves DI. When an instance of an interface is requested, the container looks in its registry to find what class has been registered for that interface. It then looks at the constructor of the class, and its parameters. These parameters should be list of interfaces that the class depends on. It then looks into its registry to find what concrete class has been registered for those interfaces, instantiates them and pass them to the constructor of the requested object. If any of the classes needed for the constructor has dependencies, these dependencies are also resolved.

So our ILogger example above would be handled like the code below. I have chosen to use Unity in the example. The choice of IoC container is, as I mentioned before, irrelevant. Just choose one that you like and that has the features you require. The reason I choose Unity is that it is a part of the Composite Application Library that I already  have on my computer.

IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<ILogger, Logger>();
MyClass myClass = myContainer.Resolve<MyClass>();

 

The interesting thing to note in the above code is the fact that the MyClass instance will now automatically have gotten the Logger passed into the constructor as this was requested. And if there was ever a need to switch the ILogger implementation, we would only need to changed the registration.

Speaking of registration, this can be moved to external XML configuration for most containers if needed. That makes it very flexible, however the XML files as often a bit complicated and they don’t offer us the control that code configuration does. If we rename a class, our code won’t build if we use code configuration, while in the XML case it will just fail when we try to run it. And with the added decoupling and “auto magic” we now use, it can sometimes be hard to find the error.

But as you might have thought of, we have now introduced another dependency. We are now all of the sudden depending on the Unity IoC container. So every time we need to instantiate an object, we need to get hold of the UnityContainer to do so. So, we have removed a bunch of dependencies, but introduced a new one. In most situations, I don’t see this as being a huge problem. But it is an extra dependency that would be nice to get away from. It is possible to get away from this IoC container dependency by implementing another abstraction pattern on top of it if needed.

The last part of this blog post is regarding a pattern called service locator. The service locator is a class that makes it possible to locate the services needed for the execution of our code. It can be something as simple as the code below, or something a lot more complicated. The main idea is that it should be used by your classes to get access to the needed dependencies

public static class MyServiceLocator
{
public static ILogger Logger
{
get;
set;
}
}

By setting the Logger property in our configuration, all code can now access this ILogger service, and it is still configurable. So by using a service locator, you can get a lot of the same benefits that you get from dependency injection, but using another approach. The only thing is that you need to find a way to either make the locator singleton accessible to all code somehow, or by injecting it to your class. Most IoC containers work as service locators, with the added benefit of getting DI as well. So using a IoC container gives you a load of flexibility and makes it possible for you to combine these patterns to get a customized solution that works for you.

On Codeplex, there is a project called the Common Service Locator library. This library is an initiative to get people into the habit of using IoC without tying them down to a specific implementation. The problem with using IoC containers without a layer of abstraction is, as I said before, that we add a dependency to our classes. We make them dependant on for example Unity. What happens if we down the line decide that Unity is not cutting it for us. We need to switch to some other container that supports a specific feature that we found out that we need. Well, we are screwed. By using a service locator on top of our container, we can switch the container without problem. The Common Service Locator library already have adapters for the most commonly used IoC containers.

However, the Common Service Locator library itself states that it is not really needed in applications. Being able to switch container is not something that is needed in most cases. However, when building a library that might need to fit into a lot of different systems, it can be invaluable…

I hope that this has given you a bit more information how the different pieces stick together and why you should use them. IoC is definitely not going away, so you might as well dig in and get started using it.

Comments (2) -

However, the Common Service Locator library itself states that it is not really needed in applications. Being able to switch container is not something that is needed in most cases. However, when building a library that might need to fit into a lot of different systems, it can be invaluable…

Even though I mostly agree with you, there are situations when dependency injection using property injection or constructor injection is not a viable solution. In those scenarios, it can actually be very useful to use a service locator...

Comments are closed