Deliberating On Software Development

March 7, 2010

Using Ninject 2 to resolve conditional bindings with a kernel

Filed under: Uncategorized — x97mdr @ 12:25 am

A while ago I saw that Nate Kohari was working on a beta version of Ninject, called Ninject 2.  I use Ninject 1.0 in my projects and I’m really happy.  It has a clean API and is very lightweight.  Since once of the projects I use Ninject in is a batch program that has a large number of user settings I often use Ninject to configure the particular object I get based on these settings, which I keep in an object called, not surprisingly, Settings. So here is an example of what I might do:

Bind<IEngineSession>()
	.To<DeriveEngineSession>()
	.OnlyIf(context => context.Kernel.Get<Settings>().Session == SessionType.Derive);

Bind<IEngineSession>()
	.To<DonorEngineSession>()
	.OnlyIf(context => context.Kernel.Get<Settings>().Session == SessionType.Donor);

Bind<IEngineSession>()
	.To<EditEngineSession>()
	.OnlyIf(context => context.Kernel.Get<Settings>().Session == SessionType.Edit);

Note that inside of the conditional binding I resolve an instance of the Settings object and use it.  Well, when I tried to do this with Ninject 2 I ran into some big problems because the IContext is not part of the conditional binding syntax now, it is replaced by IRequest which does not have access to the Kernel.  I was quite perplexed and put off for a while until I saw that Ninject 2 was officially released.  I thought perhaps the bug was resolved so I eagerly downloaded Ninject to try it out, only to be disappointed.  There was no IKernel as part of IRequest and the ParentContext field of IRequest was null on the initial bind so I couldn’t use that to get an IKernel object to resolve my objects.

Perplexed, I posted a question to the Ninject newsgroup asking if this was a bug.  One of the things I love about Ninject is that either Nate or Ian get back to you with lightning speed and efficiency and always have an answer at the ready.  As Ian pointed out, the binding itself has a property called Kernel that I can use, rather than getting it from the binding, like so:

Bind<IEngineSession>()
	.To<DeriveEngineSession>()
	.When(request => Kernel.Get<Settings>().Session == SessionType.Derive);

Bind<IEngineSession>()
	.To<DonorEngineSession>()
	.When(request => Kernel.Get<Settings>().Session == SessionType.Donor);

Bind<IEngineSession>()
	.To<EditEngineSession>()
	.When(request => Kernel.Get<Settings>().Session == SessionType.Edit);

I am pleased as can be now since this problem was the only thing preventing me from making the switch in all of my projects!  Thanks to Nate Kohari, Ian Davis, et al. for pouring so much love into this framework and making it a shining example.  I even gave my team a tour of the repository because, unlike some open source projects, it is very well laid out and easy to use … I maybe have even stolen some ideas (like embedding NAnt directly into the working folder and providing a script to build the project on demand) into my own projects!

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: