Dependency Injection (DI):- Dependency
Injection is a Software design pattern. Before dipping into Dependency
Injection we need to understand about Dependency Inversion Principle and
Inversion of Control. After than we will be at better place to understand
Dependency Injection.
Dependency Inversion Principle: Dependency Inversion
Principle is a design pattern. It states that
1. High
Level Module should not depend on low level modules, both should depend on
Abstractions.
2. Abstractions
should not depend on detail. Detail should depend on Abstraction.
Let’s understand what the
problem was before Dependency Injection Principle introduced.
Class
WriteLog
{
Public void WriteError ()
{
//Write Log here
}
}
Class
Employee
{
// Handle to EventLog writer to write to
the logs
WriteLog objCWriteLog =null;
// This function will be called when any error ocuuerred
public void WriteError(string message)
{
if (objCWriteLog == null)
{
objCWriteLog = new CWriteLog ();
}
objCWriteLog.Write(message);
}
}
In
above example code looks fine but there is a problem. Here High level module(
Employee class) is depend of low level module, Suppose you need to send a mail
to developer id in case of error instead of writing into error file. In that
case you create a class MailSender and again put that class object in Employee
class. So you have to modify the code of Employee. And in case if there is need
to use only one object than it will have another problem.
Inversion
of Control
So
problem was solved by Dependency Inversion Principle. Dependency Inversion
Principe states that every module should be decouple instead of tight couple,
such a way that higher level module should depend on simple Abstraction rather
than concrete implementation.
Let’s
understand with an example
First
create an Interface
public interface ILog
{
void WriteError (string text);
}
Than modify the Employee
class as
Class Employee
{
ILog writer =null;
// This function will be called when there is an error
public void WriteError(string message)
{
writer.Write(message);
}
}
And WriteLog class will be
change like that
class
WriteLog: ILog
{
public void WriteError (string message)
{
// Write to event log here
}
}
Now it will be easy to add
one class for sending eMail
class EmailSender : ILog
{
public void WriteError (string message)
{
// Send email from here
}
}
So here we have inverted
the control similar to dependency inversion principle. Now higher level control
are dependent on Abstraction rather than lower level control. You can say this
model follow Dependency Inversion Principle now. And Employer class can be
created like that
Class
Employee
{
// Handle to EventLog writer to write to
the logs
ILog
logger =null;
// This function will be called when there is an error
public void WriteError(string message)
{
if (objCWriteLog == null)
{
logger = new CWriteLog ();
}
objCWriteLog.Write(message);
}
}
If you will see the above
class you will notice that we are back to where we have started. The concrete
class creation inside higher level class. Can we not create Employee class
completely decouple? Here is the situation where Dependency comes in picture.
Dependency Injection
Dependency Injection means
injecting the concrete implementation into a class which is using Abstraction
i.e. interface. Main purpose of Dependency Injection is remove the coupling
between classes and put the concrete implementation out of class.
There are three ways to do
Dependency Injection.
1.
Constructor Injection
2.
Method Injection
3.
Property Injection
Constructor Injection: Constructor
Injection means inject the concrete class object through constructor rather
than creating inside High Level module.
class
Employee
{
ILog action = null;
public Employee (ILog concreteImplementation)
{
this.action = concreteImplementation;
}
// This function will be called when the
app pool has problem
public void WriteError(string message)
{
action. WriteError (message);
}
}
Now Employee object will be
create like that
WriteLog
objWrtieError = new WriteLog();
Employee
objEmp = new Employee(objWrtieError);
EmailSender
objMailSender = new EmailSender();
Employee
objEmp = new Employee(objMailSender);
Method Injection: Method Injection
means is passing the concrete class object through method.
In precious approach there
was a drawback same object will use in entire class if you need different
object for different method than we use method injection.
class
Employee
{
ILog action = null;
public Employee ()
{
}
// This function will be called when the
app pool has problem
public void WriteError(ILog
concreteImplementation string message)
{
this.action = concreteImplementation;
action. WriteError (message);
}
}
Now class Employee object
will be modifiedlike that
WriteLog
objWrtieError = new WriteLog();
Employee
objEmp = new Employee();
objEmp.
WriteError(objWrtieError ,message);
EmailSender
objMailSender = new EmailSender();
Employee
objEmp = new Employee();
objEmp.
WriteError(objMailSender,message);
Property Injection: If we need to use
concrete object in different class than we use property injection.
class
Employee
{
// Handle to ErrrorLog writer to write to
the logs
ILog action = null;
public ILog Action
{
get
{
return action;
}
set
{
action = value;
}
}
// This function will be called when the
app pool has problem
public void Notify(string message)
{
action.WriteError(message);
}
}