Dependency injection is one of the very common needs of software development. There are several Inversion of Control (IoC) containers for .NET to pick from (such as Castle Windsor, Structure Map and Microsoft Unity, just to name a few). Ninject is one of the newest entries in the arena, but it's now sufficiently stable at version 2.0.
Ninject is a lightweight dependency injection framework for .NET applications. It helps you split your application into a collection of loosely-coupled, highly-cohesive pieces, and then glue them back together in a flexible manner. By using Ninject to support your software's architecture, your code will become easier to write, reuse, test and modify.
You can read more about Ninject here.
Here are few important features of Ninject:
- Provide fluent interface
- Light-weight (122 KB, version-3.0.015)
- Faster because of lightweight code generation
- Extensible (provide extensions for MVC, WCF and more)
How to setup Ninject in an application
It's very easy and straight forword to use Ninject in an application. Just install the package from the NuGet Package Manager.
Once you install the package from the package manager, it will provide a reference of the following assembly in your application.
Once you see that the assembly is present then we are allowed to use Ninject in our application. If you are interested in using Ninject in some other application other than a console application then you need to use a few more DLLs from the NuGet Package Manager. There are two basic components of Ninject called Modules and the Kernel.
Module
The Modules are the components that to register types. Modules act as independent segments of an application that take care of the binding of all the interfaces with implementations of that segment.
So, if we discuss Modules practically, it's a way to bind a class to the associated interface. For example I have one IService interface and one Serivce class. Using Module, I can bind an IService interface with the Service class.
- public class TryModule : NinjectModule
- {
- public override void Load()
- {
- Bind<IWeapon>().To<Ninja>();
- }
- }
In this example there is an interface called IWeapon and I am binding the interface in Ninja. The reason is, I have implemented the IWeapon interface within the Ninja class.
Kernel
In Ninject the Kernel is the component that controls everything. We can directly bind the interfaces with implementations in the Kernel or we can pass them wrapped as modules. Whenever we need any implementation of the mapped interface we can get it right away from the Kernel. Ninject itself comes with a built-in Kernel called StandardKernel.
Ok, here is one example of a Kernel.
- Ninject.IKernel kernal = new StandardKernel();
- kernal.Bind<IWeapon>().To<Ninja>();
And we need to bind all of our Modules to the Kernel like above.
Fine, so we understand the two core concepts and now it's time to implement Ninject in a sample application. In this example we will create one sample application, a Console application project and we will see how Ninject is used to implement a simple IoC container. Have a look at the following example.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Net;
- using Ninject;
- namespace Client
- {
- public interface IWeapon
- {
- void sord();
- }
- public class Ninja : IWeapon
- {
- public void sord()
- {
- Console.WriteLine("I am using Sord");
- }
- }
-
- public class sourav
- {
- IWeapon ObjWeapon = null;
- public sourav(IWeapon tmpWeapon)
- {
- this.ObjWeapon = tmpWeapon;
- }
-
- public void Attack()
- {
- this.ObjWeapon.sord();
- }
- }
-
- class Program
- {
- static void Main(string[] args)
- {
- Ninject.IKernel kernal = new StandardKernel();
- kernal.Bind<IWeapon>().To<Ninja>();
- var instance = kernal.Get<sourav>();
- instance.Attack();
- Console.ReadLine();
- }
- }
- }
The IWeapon interface and Ninja class are very straight forward, we have just defined the sord() function in the IWeapon interface and we have implemented it in the Ninja class, the body of sord() is too simple.
Now, in the following of those we have implemented a "Sourav" class (the class name is purposefully given, since I wanted to use the class as Ninja).
To make the class de-coupled we have implemented function injection. The Attack() function will call the sord() function internally , that has been defined within the Ninja class.
Let's return to the Main() function that seems very important.
- Ninject.IKernel kernal = new StandardKernel();
In this line , we are creating a Kernel of Ninject that we discussed earlier and we know that the Kernel is all and all of Ninject.
- kernal.Bind<IWeapon>().To<Ninja>();
Now, we are binding our Interface with an appropriate class using Bind module.
- var instance = kernal.Get<sourav>();
- instance.Attack();
In this two lines, we are solving the dependency of Ninja class over the Sourav class and then we are calling the Attack() function.
The Attack() function will execute and within the Sourav class it will call the Sord() function internally. Now please note that.
We are executing the Attack() function in the Sourav class where the Sourav class is dependent on the Ninja class without creating an object of the Ninja class.
The magic happens because we have bound the Ninja class associated with IWeapon interface to the IoC container and the IoC container has taken care of the rest of things.
Conclusion
In this article we got the basic understanding of Ninject as IoC container. Though there are many solutions other than Ninject in this area, but people love it for it's flexibility and modern approach. I wish to write a few more articles on Ninject, so if you like it please follow those too. Thanks.