NHibernate, MVC and Ninject

Monday, November 16 2009

A few weeks back I blogged about my lightning talk on bootstrapping NHibernate with StructureMap inside an ASP.NET MVC project.

Since then I finally made some time to play around with Ninject, which seems to be the most popular IoC container amongst my Readify peers these days. Ninject is very nice to use, and very simple to get started with and of course I thought about it in the context of my NHibernate sample and whether replacing StructureMap with Ninject would make for another good sample.

Note : The code here is based on the 1.0 release of Ninject, I’m sure some funkier stuff is coming in the 2.0 release.

StructureMap has a very powerful Fluent API for controlling the instancing and construction of requested types. It let me do some funky things for building an NHibernate SessionFactory and opening a new Session.

ForRequestedType<ISessionFactory>()
	.CacheBy(InstanceScope.Singleton)
	.TheDefault.Is.ConstructedBy(() => new NHibernateSessionFactory().GetSessionFactory());

ForRequestedType<ISession>()
	.CacheBy(InstanceScope.Hybrid)
	.TheDefault.Is.ConstructedBy(x => x.GetInstance<ISessionFactory>().OpenSession());



Ninject applies a different model to StructureMap by keeping the API simpler, but allowing you to plug in custom classes to control your activation.

To achieve the same task in Ninject, I’ve created a a Module for my NHibernate configuration.

I’ve specified that the ISessionFactory and ISession types be constructed by their own Providers.

public class NHibernateModule : StandardModule
{
	public override void Load()
	{
		Bind<ISessionFactory>().ToProvider(new SessionFactoryProvider()).Using<SingletonBehavior>();
		Bind<ISession>().ToProvider(new SessionProvider()).Using<OnePerRequestBehavior>();

	}
}

public class SessionProvider : SimpleProvider<ISession>
{
	protected override ISession CreateInstance(IContext context)
	{
		var sessionFactory = context.Kernel.Get<ISessionFactory>();
		return sessionFactory.OpenSession();
	}
}

public class SessionFactoryProvider : SimpleProvider<ISessionFactory>
{
	protected override ISessionFactory CreateInstance(IContext context)
	{
		var sessionFactory = new NHibernateSessionFactory();
		return sessionFactory.GetSessionFactory();
	}
}



And you’ll see I can specify that the SessionFactory has a SingletonBehavior as it’s expensive to set up, but threadsafe and designed to be a singleton.

In the sample I’ve also added a ServiceLocator. When using StructureMap if you don’t mind coupling your code to StructureMap (probably not the best idea) you can can configure your container in one place, then make calls to ObjectFactory anywhere you need to. The Ninject kernel doesn’t work this way, so we need to keep a reference to a configured kernel in a place that can be accessed by the code. Nate Kohari, the author on Ninject provides a good example of the Service Locator pattern with Ninject on his blog.

Other than those two changes, the Ninject sample is the same as the StructureMap one, you can download it here and see for yourself.

 

Comments

Miguel Madero said on 11.20.2009 at 2:55 PM

Damian,

There's a recent thread on the Ninject group about this groups.google.com/.../57297224da1d01b


Web Developer Indonesia said on 11.28.2009 at 5:55 AM

Damian,

Thanks for sharing and great code.


yogi said on 11.28.2009 at 6:24 PM

like A fish out of water... I have no idea what your on about.... perhaps one day I should learn this stuff.