Kevin McKelvin

The NH3 Music Store Part 5 – IoC with Ninject

28 August 2010

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.

public class MvcApplication : NinjectHttpApplication
{
    ...
    protected override IKernel CreateKernel()
    {
        return new StandardKernel(new MusicStoreNinjectModule());
    }
}

The ApplicationStart() 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 ApplicationStart method by default as the standard HttpApplication does.

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

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.


Kevin McKelvin

These are the online musings of Kevin McKelvin. He is the CTO at Resource Guru, and lives in Newcastle upon Tyne, UK.