Friday, April 8, 2016

Dependency Injection

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);
    }
}

No comments:

Followers

Link