The McDev Blog

Kevin McKelvin's perspective of the Ruby world.

The NH3 Music Store Part 5 – IoC With Ninject

At the end of the last post I was deciding whether to use IoC to manage my new dependency on an IMusicStoreContext. I could have made a call to the static MvcApplication.GetCurrentRequestContext(), but from an architectural point of view, that would be tightly coupling a class to another concrete resource – which is a bad design choice for testability, maintainability and malleability.

To keep the code clean, I’m going to change things around a bit to use an IoC container. I’ve read about the Ninject.Web.Mvc project and I’d like to learn how to use it, so here we go :)

I’ve downloaded and built the Ninject.Web.Mvc project, it’s now part of the lib folder in my project’s GitHub repo as well.

The Ninject MVC project provides a NinjectHttpApplication abstract class that we’ll inherit from instead of the System.Web.HttpApplication on our MvcApplication class. We’ll also override the CreateKernel() method on the NinjectHttpApplication.

1
2
3
4
5
6
7
8
public class MvcApplication : NinjectHttpApplication
{
    ...
    protected override IKernel CreateKernel()
    {
        return new StandardKernel(new MusicStoreNinjectModule());
    }
}

The Application_Start() method must be renamed to override the OnApplicationStarted method – or you can add an event binding to it in the constructor. The NinjectHttpApplication doesn’t execute the Application_Start method by default as the standard HttpApplication does.

And we’ll create the MusicStoreNinjectModule to resolve our controllers and our IMusicStoreContext like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MusicStoreNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<AccountController>().ToSelf();
        Bind<CheckoutController>().ToSelf();
        Bind<HomeController>().ToSelf();
        Bind<ShoppingCartController>().ToSelf();
        Bind<StoreController>().ToSelf();
        Bind<StoreManagerController>().ToSelf();

        // This will be injected into our controller to give us access to our context
        // without introducing a tight coupling to a static resource.
        Bind<IMusicStoreContext>().ToMethod(c => MvcApplication.GetCurrentRequestContext());
    }
}

That means I can now add a constructor to each of our controllers that accepts an IMusicStoreContext and our controller will always receive a context object that’s built for the active request.

Neat :) Again, the code’s all on GitHub.