Simplify Dependency Injection(DI) and Inversion of Control (IoC)

simplify
simplify @Image courtesy of digitalart/ FreeDigitalPhotos.net

Simplify Dependency Injection(DI) and Inversion of Control (IoC)

Welcome to CodeSpread!

We have discussed the concept briefly in one of our previous article, SOLID. Today we will try to understand them in detail.

Before moving to details,we have to remember one major point, “Inversion of Control is a principle and Dependency Injection is the implementation”. Let’s talk about the principle first.

What is Inversion of Control?

Wikipedia says “Inversion of control (IoC) is a programming technique, expressed here in terms of object-oriented programming, in which object coupling is bound at run time by an assembler object and is typically not known at compile time using static analysis.”

Phew! I didn’t understand a word out of it. It’s the time that we should rephrase it.

“Existence of dependent objects should not depend on each other”.

It works on the understanding that in our application, we keep on creating objects and sometimes creation of one object is dependent on other object means a tight coupling exists between them. Such scenario is not favorable for the application and should be avoided. We will go with a universal example to explain this scenario.


public class Car
{
private Engine engine;
public Car()
{
engine= new Engine ();
}
}

Just see the dependency between Class Car and object Engine.If we are going to create an object of Class Car, we will get an object of Engine as a package deal. OR if we dispose the car object later, object Engine will also get destroyed. More than that, Car has no control as which type of engine it requires.

Now we will apply IoC principle to it.


public class Car
{
private IEngine engine;
public Car(IEngine engine)
{
this.engine= engine;
}
}

We have passed a variable of IEngine to the constructor and with that, creation of object Engine is controlled by object Car so object Car can choose the type of Engine.The important point is object Engine will not be created by object Car and they will be loosely coupled.

The purpose of the example is

  • There is a decoupling of the execution of a certain task from implementation.
  • Every module can focus on what it is designed for.
  • Modules make no assumptions about what other systems do but rely on their contracts.
  • Replacing modules has no side effect on other modules.[Wikipedia]

What is the importance of IOC? Or Why it is required?

We figured out few points which strongly favored IoC

  • Loose coupling: Tight coupling will have lots of problem in real world applications as things tends to change in future so Loose Coupling is the most voted option available.
  • Fast and Easy Deployments: As objects or components are independent, So each of the components can be changed,recompiled and deployed without changing the whole project.
  • Flexibility: Modular Design can be easily achieved can be modules can be switched in between the flow of application swiftly.
  • Isolation: Isolation between codes can make developer’s life heaven.

Now, We will look at the implementation part.

What is Dependency Injection?

As the principle remains same, so there is no need to go into detail. But still some basic definition “Dependency injection is a software design pattern that allows removing hard-coded dependencies and making it possible to change them, whether at run-time or compile-time.” In Dependency Injection each component must declare a list of dependencies required to perform the task. At run-time a special component (generally) called an IoC Container performs binding between these components.There are three ways to implement Dependency Injection.

  • Constructor Injection
  • Setter Injection
  • Interface-based injection

We know the basics so Let’s use that knowledge while explaining all the above.

Constructor Injection :

We know that to achieve loose coupling, interface is the best bet so for this DI, define an interface first and the classes which inherits this interface,


Interface IAccount
{

//Definition
}
public class SavingsAccount:IAccount
{
//Implementation
}

public class CurrentAccount:IAccount
{
//implementation
}

Now we will define a class CalculateInterest and Interface define above will be passed to the constructor of the CalculateInterest class..


public class CalculateInterest
{
private IAccount account;

public CalculateInterest(IAccount  account)
{
this.account=account;
}

}

Next, we will check our code.


IAccount savingsAccount=new SavingsAccount();

IAccount currentAccount=new CurrentAccount();

CalculateInterest calculateSavingsInterest=new CalculateInterest(savingsAccount); //when using CalculateInterest class for SavingsAccount

CalculateInterest calculateCurrentInterest= new CalculateInterest(currentAccount); //when using CalculateInterest class for CurrentAccount

 

One of the major drawback of constructor injection is that once the class is instantiated, it is difficult to change the object’s dependency which is corrected in setter injection.

Setter Injection:

To resolve problem faced in constructor injection, We will not pass the interface as parameter but we will assign it to a property of the class. For that, create public property of Interface in the CalculateInterest class.


public class CalculateInterest
{
private IAccount _account;

public  IAccount Account
{
get
{
return _account;
}
set
{
_account= value;
}
}

}

Now instantiate the class and assign the required property.


IAccount savingsAccount=new SavingsAccount();

IAccount currentAccount=new CurrentAccount();

CalculateInterest calculateInterest=new CalculateInterest();

calculateInterest.Account=savingsAccount;  //when using CalculateInterest class for SavingsAccount

calculateInterest.Account=currentAccount; //when using CalculateInterest class for CurrentAccount

It’s quite clear and provides more flexibility even after creation of the object.

Interface Injection:

We can provide more flexibility by creating a method in the class CalculateInterest  which will have interface as a parameter.


public class CalculateInterest
{
private IAccount account;

public SetAccount(IAccount  account)
{
this.account=account;
}

}

Let’s see the call also.


IAccount savingsAccount=new SavingsAccount();

IAccount currentAccount=new CurrentAccount();

CalculateInterest calculateInterest=new CalculateInterest();

calculateInterest.SetAccount(savingsAccount);  //when using CalculateInterest class for SavingsAccount

calculateInterest.SetAccount(currentAccount); //when using CalculateInterest class for CurrentAccount

There is one more way to apply IoC, Service Locator.

Service Locator:

In Service Locator, dependency is not injected through any medium but retrieved through the medium of a static method.

Declare a static class and a static method inside it.


static class AccountType
{
public static IAccount getAccountType()

{

//Implementation

}
}

Now call this method from your class


public class CalculateInterest
{
private IAccount account;

public CalculateInterest(IAccount  account)
{
this.account=AccountType.getAccountType();
}

}

The main problem is static call in Service Locator, else it would have been my preferred choice.

Wrap Up

Now, we finish our journey of DI and IoC. We have learned basic concepts, importance of DI and ways of implementation. I hope after reading this article,many complexities revolving around DI and IoC will get resolved. Please mail your comments or articles at admin@codespread.com

Author: hershey

A passion for knowledge drives me to do programming, A passion for programming drives me to create something different, A passion for creation drives me to spread the knowledge.

Share This Post On

0 Comments

  1. nice superb explaination

    Post a Reply
  2. thanks for the tutorial
    I am having a problem.
    The feature “Create SQL server database” isn’t available , I can’t select it.
    Can you help, please ?

    Post a Reply

Submit a Comment

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

More from CodeSpread:

  • C#: Singleton Design PatternC#: Singleton Design PatternWe know the existence of a design pattern is dependent on a recurring problem. Once the problem is identified, then a well established solution is proposed theoretically and different implementatio...
  • DI: Dependency Injection SummaryDI: Dependency Injection SummaryHere is a summary of Dependency Injection implementation. This ppt is also available for download. You can also check the same ppt on our youtube channel. http://youtu.be/BSzLwXmV7k0
  • Agile Encounters UnpredictabilityAgile Encounters UnpredictabilityWhat is Agile? Wikipedia says “Agile software development is a group of software development methods based on iterative and incremental development, where requirements and solutions evolve through...
  • Few lines about Static code analysisFew lines about Static code analysisStatic code analysis We divide the term into two parts: Static+code analysis. Static in programming can be referred to as non-running/non-dynamic and code analysis is a process where the code is...
  • Concepts: S O L I DConcepts: S O L I DSOLID - Object oriented programming principles. May be its easy to forget these principles  but for creating a reusable code or maintainable code, people will always have to come back and check ...
  • IIS Pre-ArticleIIS Pre-ArticleI thought of sharing few articles on IIS so when I started my mission, I realized that there should be some basic tasks related to IIS which needs to be done by the user before diving deep into IIS...
  • Nice reference for C# evolution Part 2Nice reference for C# evolution Part 2We completed till C# 2.0 introductions in last article. We will forward our journey with C# 3.0 features. C# 3.0 Lambda Expressions: Last article, we discussed anonymous function and how they ex...
  • base and this keyword in C#base and this keyword in C#I have seen programmers getting confused with keywords like 'base' and 'this'. Although self-explanatory, still requires basic knowledge of scope to dive in deep. Let's take them one by one. ba...