Tuesday, June 10, 2014

Inversion of Control


The purpose of IOC is to build loosely coupled software architecture.
To understand the need of loosely coupled architecture, let me explain the problem with tight coupling.
Consider following example:

Consider following class of Employee

public class Employee
    {
        int empNo;
        string empName;

        Address empAddress;
        public Employee()
        {
            empAddress = new Address();
        }
    }

The problem here is that Employee and Address classes are tightly coupled with each other.
Any change in Address class will affect Employee class implementation and will require change in Employee class.

Employee class is aware of the address class. So if we add new address types like home address, office address etc it will require change in customer class.
Here we say class Employee has dependency on class Address.
This situation has the following problems:
  • To replace or update the dependencies, we need to change our class’s source code.
  • The concrete implementations of the dependencies have to be available at compile time.
  • Our classes are difficult to test in isolation because they have direct references to dependencies
  • Our classes contain repetitive code for creating, locating, and managing their dependencies.
Solution to this problem is to decouple the classes and Delegate the task of managing the dependencies to external component.
In other words we have to invert the control of creating dependencies to a third party.

Any of the following conditions justifies using the solution described in this pattern:
  • You want to decouple your classes from their dependencies so that the dependencies can be replaced or updated with minimal or no changes to your classes' source code.
  • You want to write classes that depend on classes whose concrete implementations are not known at compile time.
  • You want to test your classes in isolation, without using the dependencies.
  • You want to decouple your classes from being responsible for locating and managing the lifetime of dependencies.
IOC can be implemented in several ways. The Dependency Injection pattern and the Service Locator pattern are specialized versions of this pattern.

Dependency Injection using Windsor container

Here I am explaining Dependency Injection using Windsor container.

Typically, you express dependencies on interfaces instead of concrete classes. This enables easy replacement of the dependency concrete implementation without modifying your classes' source code.

To create loose coupling we will Create a interface IAddress and create a concreate class Address from this interface. 
We will pass the object of IAdress to Employee class constructor and hence if we have to add a new class as HomeAddress we will create a new class HomeAddress implementing IAdress interface and there will be no need to change the code in Employee class.

public class Employee
    {
        int empNo;
        string empName;

        IAddress empAddress;
        public Employee(IAddress address)
        {
            this.empAddress = address;
        }
    }
public interface IAddress
    {
    }

    public class Address : IAddress
    {
        public string address;
        public string city;
        public string state;

        public Address()
        {
            this.address = "Default Address";
            this.city = "Default City";
            this.state = "Default State";
        }
    }

Now here in this example class Employee have dependency on class Address and if we were to create object of class Employee without using Dependency Injection we will have to manually create objects of all dependencies (in this case Address class object) and pass it to Employee class creation as follows:

/* Manually Creating Dependency object i.e.Address and passing it while creating Employee object */
            Address address = new Address() { address = "M.G.Road", city = "Shirur", state = "Maharashtra" };
            Employee emp = new Employee(address);


Using Dependency Injection

Here I am using Castle Windsor as Dependency Injection container and there are many DI containers available which you can use.
On application startup we will create object of Castle Windsor and will register all components in this container.
/* Using Dependency Injection using Castle Windsor */
            WindsorContainer _windsorContainer = new WindsorContainer();
           
            // Register All types manually
            _windsorContainer.Register(Component.For<IAddress>().ImplementedBy<Address>());
            _windsorContainer.Register(Component.For<Employee>());

We can manually register all types in WindsorContainer as shown above or we can register all types in the assembly as shown below.
// Register All types in current assembly
            _windsorContainer.Register(Castle.MicroKernel.Registration.AllTypes.FromThisAssembly().Pick()
                                  .WithService.DefaultInterfaces().AllowMultipleMatches());

To create object of Employee using DI you do not need to create object of Address class. DI will automatically inject address object in Employee object.
Create Employee object as shown below

var objEmployee = _windsorContainer.Resolve<Employee>();


This is all about the concept of IOC.

Do spend your time to provide comments and feedback over here or on my mail id narenkedari@gmail.com 


No comments:

Post a Comment