Inversion of control is one of the design patterns, which help us to
build decoupled software components. Let’s see that with one of the very common
example over Internet
public
class clsCustomer
{
Private clsAddress _address
public clsCustomer ()
{
_address = new clsAddress();
}
}
Here we can see two problems
1.
clsCustomer
is having reference of clsAddress.
2. clsCustomer is aware of concrete
address class.
So the main problem is Tight Coupling. This problem is created by approach followed
for object creation so solution is somehow we have to make sure that
clsCustomer must not be holding reference of address class. We can achieve this by following principle of
Inversion of control which states:
- · High level modules should not depend upon low level modules. Both should depend upon abstractions.
- · Abstractions should not depend upon details. Details should depend upon abstractions.
In other
popular words its stands on the base of Hollywood principle (response given to
amateurs auditioning in Hollywood): Do not call us we will call you.
It’s like address class saying to the customer
class, do not create me I will create myself using someone else. The simplest
way would be to expose a method which allows us to set the address object.
public
class clsCustomer
{
Private IAddress _address
public clsCustomer (IAddress address)
{
_address = address;
}
}
And now
question is who will be someone else? And answer is IOC Containers. We have several
containers around e.g. Structure Map, Ninject, Unity, Windsor etc. By using any of these Containers we can
implement Dependency injection and let object creation to be delegated to our
Container.
I’ll discuss
here Ninject along with MVC 4. Let’s create MVC 4 Internet application and name
that “MVC4WithNinject” now it will look as follows
Let’s add Ninject
NuGet package:
Don’t worry
that it says MVC3 – it works in MVC 4 as well. This will add a new class NinjectWebCommon
in app_start folder.
NinjectWebCommon
class has start, stop, CreateKernel and RegisterServices methods. At this stage will be able to build and run
application, home page will look as follows:
If you look
at the HomeController class definition, then you will find that the class
has no constructor. We all know that if there is no constructor
defined then at compile time .NET Framework creates a default
parameter-less constructor.
public
class HomeController : Controller
{
public HomeController()
{
}
}
Now I will create ILogger interface and its implementation DefaultLogger class. Home controller class will use that
ILogger object. I will inject it throw constructor.
public interface ILogger {
void Log(string logData);
}
public class DefaultLogger : ILogger {
public void Log(string logData)
{
System.Diagnostics.Debug.WriteLine(logData, "default");
}
}
Let’s pass ILogger into HomeController,
now code will look as follows:
public class HomeController :
Controller {
private readonly ILogger _logger;
public HomeController(ILogger logger)
{ _logger = logger; }
}
Let’s run application again, as we
have created a parametrized constructor it will throw error
All we need to do is to tell
Ninject to provide instance of DefaultLogger when ILogger is used. We can do this by adding following lines into
RegisterServices method:
private static void
RegisterServices(IKernel kernel) {
kernel.Bind<ILogger>().To<DefaultLogger>();
}
Now if we’ll run application
again we’ll able to see home page again.
This was simplest example of
implementation of Dependency injection using Ninject as Inversion of control container.
I hope this discussion had given you
basic understanding of IoC and DI. For other details refer Head First Design
Patterns or internet you will get other implementation approach for Dependency
injection .Let me know if any question.
Courtesy: MSDN , Head First Design Patterns & Several other
online resources.