Dependency Injection Explained

By | June 26, 2015

This is going to be a short c# based tutorial on Dependency Injection.
Newcomers find it difficult to grasp concept of Dependency Injection. I will attempt to explain in simplest terms possible.

As usual, I will deal first with “WHY” and then the “HOW”.

WHY

It is all about removing dependencies from your code. In other words, these help you to decouple your components.

Decouple what?
In caveman simple terms, it means that one software module does not know about other module.

There are many benefits.

1 – When one module changes, other modules need not be changed. Code refactoring made easy.
2 – The module is reusable because it is standalone. It can be plugged in with minimum fuss.
3 – It is easier to test modules which do not have dependencies.
4 – If all this does not help, think of LEGO. You make a structure out of LEGO’s. Each LEGO piece is a software module. The structure is your software solution.

legoBlock

HOW

We will start off with a sample.

Here we see that BatmanBattery and TeslaTuner implement the IBattery and ITuner.

public class BatmanBattery: IBattery
{
	public string Type { get; set; }
}
   
public class TeslaTuner : ITuner
{
	public string Brand { get; set; }
}

Here is Radio class that uses these two components.

//--Without  Dependency Injection---
public class Radio
{
	public IBattery Battery { get; set; }
	public ITuner Tuner { get; set; }
	
	public Radio()
	{
		Battery = new BatmanBattery ();
		Tuner = new TeslaTuner();
	}
	public void Play();
}

And here is client code.

public class Demo
{
	public static void Main(string[] args)
	{
		Radio radio = new Radio();
	}
}

Do you see a problem there?

The Radio class now knows about BatmanBattery and TeslaTuner. If these classes change then your Radio class gets affected. Suppose a new tuner called TallyHoTuner is in the market. Now you have to update the Radio class if you want to use the new tuner.

Unit testing of Play() method of the Radio is now difficult. Your unit test code will execute code from BatmanBattery and TeslaTuner class (Constructors). Your unit test is not just covering the Radio class. It has code from BatmanBattery and TeslaTuner class also in its scope.

Now let us make some changes

//-- With Dependency Injection ---
public class Radio
{
	public IBattery Battery { get; set; }
	public ITuner Tuner { get; set; }

	public Radio(IBattery battery, ITuner tuner)
	{
		Battery = battery;
		Tuner = tuner;
	}
}

public class Demo
{
	public static void Main(string[] args)
	{
		Radio radio = new Radio(new BatmanBattery (),new TeslaTuner());
	}
}

What have we done here?

We now pass the Battery and the Tuner object to the constructor of the Radio class. This simple act has actually done quite a lot.

  1. Notice that now Radio class just knows about the interface and not the implementation.
  2. BatmanBattery and TeslaTuner can be changed at will. No need to recompile the Radio class.
  3. The end user can pass object of any class to the Radio. Provided the class implements the interface Radio class expects.
  4. Now in unit tests you can actually pass on the Fakes implementing the IBattery and ITuner interfaces. This means that now you test only Radio class. This is BIG win in my books.
    To put this in context, I had to unit test login service which used LDAP. LDAP can return many error codes which deal with cases like Login Expired, Change your Password, Account locked and what not. There was no real way I could have done that with company LDAP server. Setting up my own for unit testing was not feasible. So I created a LADP mock which returned these error codes and used it. Smooth.

Dependency Injection can be achieved in 3 different ways:
1 – Constructor Injection – Most common
(The above examples are dependency injection achieved via Constructor Injection)
2 – Setter Injection – Not so common
3 – Method Injection – Rare

There is also something called interface injection but frankly speaking it is not worth mentioning. If you implement “Program to the interfaces” then you are good. In all the three types of Dependency Injection I am illustrating, I am working with Interfaces only.

Constructor Injection
It is a simple way of creating objects. You pass all the dependencies your class needs to the constructor of the class. It helps in testing. It can become a bit tedious when the class has too many dependencies. You have already seen the implementation in the examples given till now.

Setter Injection
In this the dependencies are exposed as the public members of the class. A parameterless constructor is used to create the object. Then the properties are directly set. The previous example reworked to reflect Setter Injection is below.

//-- With Dependency Injection via setters ---
public class Radio
{
	public IBattery Battery { get; set; }
	public ITuner Tuner { get; set; }

	public Radio()
	{}
}

public class Demo
{
	public static void Main(string[] args)
	{
		Radio radio = new Radio();
		radio.Battery = new BatmanBattery ();
		radio.Tuner = new TeslaTuner();
	}
}

This method has some issues.
– You “might” forget to set some of the needed properties. And compiler will not give you any warning.
– If the order in which the properties have to be set matters then you have got one more way of failing. An out of order property initialisation.

Method Injection.
This is still rarer form of Dependency injection. Sometimes you have a class in which only one method needs that dependency. In that case that method is passed the dependency directly leaving rest of the code untouched.

Let us rework our radio again.

//-- With Dependency Injection via method injection ---
public class Radio
{
	public Radio()
	{}
	
	public Charge(IBattery battery)
	{
		//Some work. Important thing is that the rest of the class does 
		//care about IBattery.
	}
}

public class Demo
{
	public static void Main(string[] args)
	{
		Radio radio = new Radio();
		radio.Charge(new BatmanBattery ());
	}
}

Many people often confuse Dependency Injection with Dependency Inversion Principle. That will be subject of another post.
If you have time then I recommend that you have a read through this excellent article by Martin Fowler on this subject.

2 thoughts on “Dependency Injection Explained

  1. Lucky

    A very Good Explanation of the topic sir.I appreciate your efforts.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.