What is the intention of Ninject modules?
Asked Answered
H

3

59

I'm a complete newbie to ninject

I've been pulling apart someone else's code and found several instances of nInject modules - classes that derive from Ninject.Modules.Module, and have a load method that contains most of their code.

These classes are called by invoking the LoadModule method of an instance of StandardKernel and passing it an instance of the module class.

Maybe I'm missing something obvious here, but what is the benefit of this over just creating a plain old class and calling its method, or perhaps a static class with a static method?

 

Hirohito answered 13/1, 2010 at 12:1 Comment(0)
H
62

The Ninject modules are the tools used to register the various types with the IoC container. The advantage is that these modules are then kept in their own classes. This allows you to put different tiers/services in their own modules.

// some method early in your app's life cycle
public Kernel BuildKernel()
{
    var modules = new INinjectModule[] 
    {
        new LinqToSqlDataContextModule(), // just my L2S binding
        new WebModule(),
        new EventRegistrationModule()
    };
    return new StandardKernel(modules);
}

// in LinqToSqlDataContextModule.cs
public class LinqToSqlDataContextModule : NinjectModule
{
    public override void Load()
    {
        Bind<IRepository>().To<LinqToSqlRepository>();
    }
}

Having multiple modules allows for separation of concerns, even within your IoC container.

The rest of you question sounds like it is more about IoC and DI as a whole, and not just Ninject. Yes, you could use static Configuration objects to do just about everything that an IoC container does. IoC containers become really nice when you have multiple hierarchies of dependencies.

public interface IInterfaceA {}
public interface IInterfaceB {}
public interface IInterfaceC {}

public class ClassA : IInterfaceA {}

public class ClassB : IInterfaceB
{
    public ClassB(IInterfaceA a){}
}

public class ClassC : IInterfaceC
{
    public ClassC(IInterfaceB b){}
}

Building ClassC is a pain at this point, with multiple depths of interfaces. It's much easier to just ask the kernel for an IInterfaceC.

var newc = ApplicationScope.Kernel.Get<IInterfaceC>();
Husserl answered 13/1, 2010 at 12:18 Comment(9)
LinqToSqlDataContextModule should extend StandardModule?Apc
@Mark Gibaud not in Ninject 2. StandardModule is gone and replaced with NinjectMdule - github.com/enkari/ninject/tree/master/src/Ninject/ModulesHusserl
That's a good example, but what about testability? I constantly hear how an DI/IoC container can help me with testability, but I'm having a hard time to find a real example that would showcase that Ninject won't pollute my code and also facilitate testability. Are there any real world open source projects that I could look at to get the idea?Geum
Another problem is Ninject documentation. Are those guys ever going to provide such thing? Ninject is currently in version 2.0 and I can't even find solid documentation on 1.0.Geum
@Piotr Owsiak What Ninject documentation? :)Husserl
@Jarrett Meyer: Exactly man! What documentation? AFAIK it just does not exists.Geum
It's an open-source project. If you're interested in documentation, gotta pitch-in and write some. :) But in Ninject's case, I found that the unit tests were pretty good documentation, and by definition, the unit-tests will always change with the code so it's always up to date.Candi
@PiotrOwsiak: DI/IoC container itself doesn't help with testability... what helps is the fact that you're building loose modules that can then be tested, and once you're satisfied with the results, you can use Ninject, Unity, Castle Windsor, etc. to glue them together within your application.Sempstress
@RichardB: Thanks for reply, since then I already have drunk the cool aid and got a much thorough understanding of Ninject and DI/IoC in general (and even SL). I guess IoC containers are one of those things that you have to try to really understand the idea behind it, theory is just 80% but when you try it yourself you get the ramaining 20% a nothing is based on faith but rather experience.Geum
W
9

Maybe I'm missing something obvious here, but what is the benefit of this over just creating a plain old class and calling its method, or perhaps a static class with a static method?

Yes, you can just call a bunch of Bind<X>().To<Z>() statements to setup the bindings, without a module.

The difference is that if you put these statements in a module then:

  • IKernel.Load(IEnumerable<Assembly>) can dynamically discover such modules through reflection and load them.
  • the bindings are logically grouped together under a name; you can use this name to unload them again with IKernel.Unload(string)
Wey answered 13/1, 2010 at 14:8 Comment(0)
T
3

Maybe I'm missing something obvious here, but what is the benefit of this over just creating a plain old class and calling its method, or perhaps a static class with a static method?

For us, it is the ability to add tests at a later time very easily. Just override a few bindings with mockobjects and voila.....on legacy code without a DI that wired "everything" up, it is near impossible to start inserting test cases without some rework. With a DI in place AND as long as it was used properly where the DI wired everything up, it is very simple to do so even on legacy code that may be very ugly.

In many DI frameworks, you can use the production module for your test with a test module that overrides specific bindings with mockobjects(leaving the rest of the wiring in place). These may be system tests more than unit tests, but I tend to prefer higher level tests than the average developer as it tests the integration between classes and it is great documentation for someone who joins the project and can see the whole feature in action(instead of just parts of the feature) without having to setup a whole system).

Trip answered 28/12, 2011 at 14:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.