Dependency Injection
MVC design pattern enables separation of concerns. Helping us to develop more independent components in our application. This is how we can implement loose coupling, and it helps testing and maintenance of our application easy. So Dependency Injection helps in making your application’s components more loosely coupled.
There are software design patterns out of which Dependency Injection(DI) is the one that allows us to develop loosely coupled code, which greatly reduces tight coupling between developed components. DI enables us to manage changes and other complexity in our application. The purpose of DI is to make code maintainable.
While programming with DI designed classes are more loosely coupled because they do not have direct dependencies on their collaborators. This is how you can follow Dependency Inversion Principle. By definition of Dependency Inversion Principle[1], "High level modules should not depend on low level modules (which shows loose coupling); both should depend on abstractions." Instead of depending on something, classes point to abstractions (typically interfaces) which are provided to them at the time of designing the class.
Below are the three ways of achieving Dependency Injection.
- Dependency Injection via Constructor Injection.
- Dependency Injection via Method Injection.
- Dependency Injection via Property Injection.
Constructor Injection :
Problem
Lets have three low level classes or modules.
//first Low level class
class Sum
{
public void calculate(int a, int b)
{
Console.WriteLine(a + b);
}
}
//second Low level class
class Subtract
{
public void calculate(int a, int b)
{
Console.WriteLine(a ‐ b);
}
}
//third Low level class
class Multiply
{
public void calculate(int a, int b)
{
Console.WriteLine(a * b);
}
}
Higher Level Module
class Calculation
{
Sum s = null;
public void doCalculation(int a, int b)
{
s.calculate(a, b); //here high level module depends on low level module
}
// for calling Subtract or Multiply we have to create instances and dependency is there
}
What problem can we have?
While following this design,you will fail to have the (DIP) Dependency Inversion Principle. Class Calculation depends on class Sum, which is a low level class. We can call “Subtract” and “Multiply” classes also like this, but we will use only one object at a time. Using this, we have to use all the objects at the same time, which we don’t want to use.To achieve Dependency Injection, we have used the approach given below :
Interface for Dependency Injection
//Interface for dependency Injection
interface ICalculate
{
void calculate(int a, int b);
}
Low Level Modules
//first Low level class
class Sum :ICalculate
{
public void calculate(int a, int b)
{
Console.WriteLine(a + b);
}
}
//second Low level class
class Subtract : ICalculate
{
public void calculate(int a, int b)
{
Console.WriteLine(a ‐ b);
}
}
//third Low level class
class Multiply : ICalculate
{
public void calculate(int a, int b)
{
Console.WriteLine(a * b);
}
}
High level Module
//high Level module
class Calculation
{
ICalculate cal= null;
//Constructor
//Dependency Injection via constructor
public Calculation(ICalculate iCal)
{
this.cal = iCal;
}
public void doCalculate(int a, int b)
{
cal.calculate(a, b);
}
}
We will call the method, which we require, as shown below.
static void Main(string[] args)
{
Sum s = new Sum();
Calculation calc= new Calculation(s);
s.calculate(6, 5);
Console.Read();
}
Hence, there is no dependency now. We have done the Constructor Injection, while we are injecting the dependency in constructor only.
Method Injection
As the name suggests, the dependent injection can be achieved by injecting an object, using the method inside the class. As we see in constructor injection, concrete class is used by dependent class throughout the life cycle. But what if for invocation of method, we need separate concrete class. At this time, we have to pass dependency at method only instead of constructor.
In Method Injection, we pass the object of the concrete class into the method of the dependent class.
Here, we pass the object of the class, which we want to use, which may be Sum, Subtract or Multiply into the method of Calculation class (method's name is doCalculate).
Method Injection can be implemented as given in below example .
interface ICalculate
{
void calculate(int a, int b);
}
class Sum : ICalculate
{
public void calculate(int a, int b)
{
Console.WriteLine(a + b);
}
}
//second Low level class
class Subtract : ICalculate
{
public void calculate(int a, int b)
{
Console.WriteLine(a ‐ b);
}
}
//third Low level class
class Multiply : ICalculate
{
public void calculate(int a, int b)
{
Console.WriteLine(a * b);
}
}
//high Level module
class Calculation
{
ICalculate cal= null;
//Constructor
//Dependency Injection via constructor
//Method Injection
public void doCalculate(ICalculate iCal, int a, int b)
{
this.cal = iCal;
cal.calculate(a, b);
}
}
class MethodInjection
{
static void Main(string[] args)
{
Sum s = new Sum();
Calculation calc= new Calculation();
calc.doCalculate(s, 5, 6);
Console.Read();
}
}
Here, we are passing the object of the Sum Class s and the parameters 5 and 6.
public void doCalculate(ICalculate iCal, int a, int b)
{
this.cal = iCal;
cal.calculate(a, b);
}
//Calling Or Intializing
Sum s = new Sum();
Calculation calc = new Calculation();
calc.doCalculate(s, 5, 6);
If we want to use any other class other than Sum, we can pass the object of that class here.
Property Injection
As we have seen in the two cases, mentioned above, In Constructor Injection Dependent class, we will use one concrete class for the entire lifetime and the in Method Injection, we will pass the object of the concrete class into the method of the dependent class. In a case, when both the concrete classes and the high level modules are in different places (modules), how can we achieve the Dependency Injection? This is where Property Injection comes into play.
In Property Injection, we use a setter property in the High Level Module/ Dependent class by passing the object of the concrete class via this setter property. Here, the setter property will take the object of the concrete class and pass it to the Interface of the dependent class.
interface ICalculate
{
void calculate(int a, int b);
}
class Sum : ICalculate
{
public void calculate(int a, int b)
{
Console.WriteLine(a + b);
}
}
//second Low level class
class Subtract : ICalculate
{
public void calculate(int a, int b)
{
Console.WriteLine(a ‐ b);
}
}
//third Low level class
class Multiply : ICalculate
{
public void calculate(int a, int b)
{
Console.WriteLine(a * b);
}
}
//high Level module
class Calculation
{
ICalculate cal= null;
//Property Setter where this property will be set by Object of the class
public ICalculate Cal
{
get
{
return cal;
}
set
{
cal= value;
}
}
//Method Injection
public void doCalculate(int a, int b)
{
cal.calculate(a, b);
}
}
class PropertyInjection
{
static void Main(string[] args)
{
Sum s = new Sum();
Calculation calc = new Calculation();
calc.Cal = s;
calc.doCalculate(3, 4);
Console.Read();
}
}
Property Injection is also called Setter Injection.
Hope you understood it better : )
Thank you
References: