I have been helping a few friends on a project and there is a class that uses Ninject. I am fairly new to C# and I have no idea what that class is doing, which is why I need to understand Ninject. Can anyone explain what Ninject is and when does one use it(with example if possible)? Or if you can point to some links that would be great too.
I tried this question: Ninject tutorials/documentations? but it didn't really help a beginner like me.
Ninject helps you use the technique of dependency injection to break your applications into loosely-coupled, highly-cohesive components, and then glue them back together in a flexible manner.
Using dependency injection, we can pass an instance of class C to class B, and pass an instance of B to class A, instead of having these classes to construct the instances of B and C. In the example, below, class Runner has a dependency on the class Logger.
You can waste days evaluating IOC containers. The top ones are quite similar. There is not much in this, but the best ones are StructureMap and AutoFac.
In software engineering, dependency injection is a design pattern in which an object or function receives other objects or functions that it depends on. A form of inversion of control, dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs.
Ninject is dependency injector for .NET, practical realisation of pattern Dependency Injection (form of Inversion of Control pattern).
Suppose you have two classes DbRepository
and Controller
:
class Controller { private DbRepository _repository; // ... some methods that uses _repository } class DbRepository { // ... some bussiness logic here ... }
So, now you have two problems:
You must initialize _repository
to use it. You have several options for doing this:
Controller
class because code it's dependent upon was changed. It's not hard if you have only one Controller
, but if you have a couple of classes that have a dependency on your Repository
you have a real problem.You can use a service locator or factory. But now you have a dependency on your service locator. You have a global service locator and all code must use it. How you will you change the behavior of your service locator when you need to use it in one part of your code for activation logic but for something else in another part of your code? There is only one way - passing the service locator through constructors. But with more and more classes you will need to pass it more and more times. Anyway, it's a good thought but in the long run, it's a bad idea.
class Controller { private DbRepository _repository; public Controller() { _repository = GlobalServiceLocator.Get<DbRepository>() } // ... some methods that uses _repository }
You can use dependency injection. Look at the code:
class Controller { private IRepository _repository; public Controller(IRepository repository) { _repository = repository; } }
Now when you need your controller you write: ninjectDevKernel.Get<Controller>();
or ninjectTestKernel.Get<Controller>();
. You can switch beetween dependency resolvers as fast as you want. See? It's simple, you don't need to write a lot.
You can't create unit tests for it. Your Controller
has a dependency on DbRepository
and if you want to test some method that uses repository, your code will go to the database and ask it for data. That's slow, very slow. If your code in DbRepository
changes, your unit test on Controller
will fall. Only integration test must warn you of 'problems' in this case. What you need in unit tests - is to isolate your classes and test only one class in one test (in ideal - only one method). If your DbRepository
code fails, you will think that Controller
code failed - and that's bad (even if you have tests for DbRepository
and Controller
- they both will fail and you can start from the wrong place). It takes a lot of time to determine where the error really is. You need to know that class A is ok, and it was class B where something failed.
When you want to replace DbRepository
with something else in all your classes, you have to do a lot of work.
You can't easily control the lifetime of DbRepository
. An object of this class is created on initialization of Controller
and deleted when Controller
is deleted. There is no sharing between different instances of the Controller
class and there is no sharing between other classes. With Ninject you can simply write:
kernel.Bind<IRepository>().To<DbRepository>().InSingletonScope();
A special feature of dependency injection - agile development! You describe that your controller uses a repository with interface IRepository
. You don't need to write DbRepository
, you can simply create a MemoryRepository
class and develop Controller
while another person develops DbRepository
. When work on DbRepository
is finished, you just rebind in your dependency resolver that default IRepository
is now DbRepository
. Have a lot of controllers? All of them will now use DbRepository
. That's cool.
Read more:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With