Inversion of control (IoC) describes a design in which custom-written portions of a computer program receive the flow of control from a generic, reusable library. A software architecture with this design inverts control as compared to traditional procedural programming: in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the reusable code that calls into the custom, or problem-specific, code.
Let's try to understand the inversion of control in with an example. Suppose, we have a console application with a sequence of commands like "Enter name", "enter address"; this program would drive the prompts and pick up a response to each one. With graphical (or even screen based) UIs the UI framework would contain this main loop and your program instead provided event handlers for the various fields on the screen. The main control of the program was inverted, moved away from you to the framework.
Implementing Inversion of Control:
Now, let's create it with an example. We are creating a program in which there is a VehicleController is the higher level module, which consumes and uses the lower level module Car. If you want to change the vehicle to Truck instead of Car then VehicleController does not require any change if there is higher level of abstraction.
Applying Inversion of Control (IoC)
Inversion of Control is a technique to implement the Dependency Inversion Principle in C#. Inversion of control can be achieved by using interfaces or abstract class. The rule is that the lower level modules should use a single interface and the higher level module will consume only modules that are implementing the interface. By following this technique, we can remove the dependency between the modules. Following diagram shows the UML for our example.
Now, let’s try to create the code by using above UML diagram. There is an Interface Named IVehicle with two methods.
public interface IVehicle
{
void Accelerate();
void Brake();
}
We have classes named Truck and Car which derived this interface. Following are the codes-
public class Car : IVehicle
{
#region IVehicle Members
public void Accelerate()
{
Console.WriteLine("Car accelerates...");
}
public void Brake()
{
Console.WriteLine("Car stopped.");
}
#endregion
}
public class Truck : IVehicle
{
#region IVehicle Members
public void Accelerate()
{
Console.WriteLine("Truck accelerates...");
}
public void Brake()
{
Console.WriteLine("Truck stopped.");
}
#endregion
}
And, finally we have a controller class called VehicleController with a constructor and responsible to create objects by using interface IVechile. The code will be
public class VehicleController
{
IVehicle m_Vehicle;
public VehicleController(IVehicle vehicle)
{
this.m_Vehicle = vehicle;
}
public void Accelerate()
{
m_Vehicle.Accelerate();
}
public void Brake()
{
m_Vehicle.Brake();
}
}
And, let’s use this program by creating a main method.
class Program
{
static void Main(string[] args)
{
IVehicle vehicle = new Car();
//IVehicle vehicle = new Truck();
VehicleController vehicleController = new VehicleController(vehicle);
vehicle.Accelerate();
vehicle.Brake();
Console.Read();
}
}
Here the main products (e.g. - car) are completely decoupled from the consumer using the IVehicle interface. The object is injected into the constructor of the VehicleController class in reference with the interface IVehicle. The constructor where the object gets injected is called as Injection Constructor.
So what is Inversion of Control Container?
By analyzing above code sample, the Car or Truck object creation is still present in the Main method, which is again a dependency. But, in IoC technique the creation of the object will also be delegated to a separate component or framework, which will take care of creating and injecting the dependency object. This is called dependency injection and the component accomplishing the task is called the IoC container. There are nothing to do with production application, we are just coding exercise and should not be used in a production application. Instead you can use one of the many existing IoC containers for .NET:
You can also create your own custom IoC container using reflection and generics in C#. My aim to provide you to an examination about IoC container and this article has provided enough information about the Inversion of Control. Here we have a sample IoC container.
public class IocContainer
{
private readonly Dictionary<type, type=""> _dependencyMap =
new Dictionary<type, type="">();
public T Resolve<t>()
{
return (T)Resolve(typeof(T));
}
public void Register<tfrom, tto="">()
{
_dependencyMap.Add(typeof(TFrom), typeof(TTo));
}
private object Resolve(Type type)
{
Type resolvedType = LookUpDependency(type);
ConstructorInfo constructor =
resolvedType.GetConstructors().First();
ParameterInfo[] parameters = constructor.GetParameters();
if (!parameters.Any())
{
return Activator.CreateInstance(resolvedType);
}
else
{
return constructor.Invoke(
ResolveParameters(parameters)
.ToArray());
}
}
private Type LookUpDependency(Type type)
{
return _dependencyMap[type];
}
private IEnumerable<object> ResolveParameters(
IEnumerable<parameterinfo> parameters)
{
return parameters
.Select(p => Resolve(p.ParameterType))
.ToList();
}
}
Now, Let’s try to use this IoC Container in our main Program. We can write the code as given below
static void Main(string[] args)
{
var container = new IocContainer();
container.Register<vehiclecontroller, vehiclecontroller="">();
container.Register<car,truck>();
var vehicle = container.Resolve<vehiclecontroller>();
vehicle.Accelerate();
vehicle.Brake();
Console.ReadLine();
}
Summary: Here we have created a simple program using inversion of control and then created a Inversion of Control Container and use it.
References:
http://en.wikipedia.org/wiki/Inversion_of_control
http://martinfowler.com/articles/injection.html