My DI container of choice is Ninject. The reasons aren’t overly important, other than I hate, hate, hate XML. If I wanted to program in XML, I’d use Java. Fortunately, there are DI containers in the .Net space that don’t require all that XML, and Ninject is one of them. The Ninja connections kinda bug me, but I actually had it in my head as NINject first, so Trent trumps stupid martial arts posing.
The first thing I came across while trying to get into MassTransit, though, is that Ninject support, while advertised as existing, is a little lacking. It could just be me, but I found a problem with using any of the non-default constructors in MassTransitModuleBase, which is derived from NinjectModule. NinjectModule is the base class from which you derive to set up your bindings, and then your derived class is passed into a Ninject Kernel, which does the binding resolution. Ninject isn’t really ready to set up bindings until the Load() override in your derived class is called, but MassTransitModuleBase tries to set up bindings in the non-default constructors using the values that are passed in.
This makes sense, because the other significant non-XML based DI container, StructureMap, appears to allow this, and clearly the MassTransit guys have used that container and used it as the model for the Ninject support. Dru Sellers, one of the original authors, told me in a tweet that they weren’t all that familiar with Ninject. Its understandable – how many DI containers do you really need to know how to use?
So, I had managed to make it work by not using any of the non-default constructors at this point, because I assumed that the MassTransit implementation was correct. The result looked something like this (note that I used Mike Hadlow’s first look article as the basis for my code):
[Gist MassTransit and Ninject Example 1.cs]public class PlayMassTransitModule : MassTransitModuleBase
{
public override void Load()
{
base.Load();
RegisterEndpointFactory(x =>
{
x.RegisterTransport<LoopbackEndpoint>();
x.RegisterTransport<MulticastUdpEndpoint>();
x.RegisterTransport<MsmqEndpoint>();
});
RegisterServiceBus(@"msmq://localhost/mt_mike_publisher", x =>
{
x.SetConcurrentConsumerLimit(1);
ConfigureSubscriptionClient(@"msmq://localhost/mt_subscriptions", x);
});
}
}
Notice that I had to set everything up in the Load() override. This is the way it has to be right now. I’m working on a patch so that you can use the Ninject container integration exactly like you do with StructureMap. Hopefully I’ll have it done and accepted by the time this post is published. In the meantime, if you want to see the full solution, check out this branch in my github DemoCode space: https://github.com/ekepes/DemoCode/tree/NinjectDemo