Ninject with NServiceBus confusions

Every now and then people get confused when they try to use the NinjectObjectBuilder for NServiceBus. In this blog post I want to describe the purpose of the NinjectObjectBuilder for NServiceBus and highlight the difference between Ninject and Ninject together with NServiceBus.

But before we dive into the Ninject object builder I want to give you a bit background about the object builder of NServiceBus and its purpose. The NServiceBus core framework has the notion of a CommonObjectBuilder. The CommonObjectBuilder holds internally an abstracted version of an inversion of control container with the interface IContainer. The common object builder exposes a set of registration methods which allow to register dependencies via the CommonObjectBuilder on the abstract container implementation. Sounds abstract and complicated? Actually there is a reason why this is built like this. As an opinionated framework NServiceBus offers an out-of-the-box mechanism for developers which might not have knowledge about a particular inversion of control container. Therefore NServiceBus offers its own set of registration methods which are well documented and maintained by the framework team. As a client of the NServiceBus API, I don’t have to know (especially if I don’t want to) any specifics about a certain container. I simply rely on the NServiceBus registration API and register my dependencies on NServiceBus. The registration API offers me only the lifetime scoping which makes sense for a messaging framework. Here is an example how this looks like:

config.Configurer.ConfigureComponent<MyDependency>(DependencyLifecycle.InstancePerCall);

It is also possible to use different scopes like:

  • InstancePerUnitOfWork which creates a new instance per physical transport message
  • SingleInstance which returns for the lifetime of an endpoint always the same instance

All this is provided as an extension mechanism on the fluent configuration started with Configure.With()… By default the CommonObjectBuilder uses Autofac as the underlying IContainer implementation and translates the NServiceBus specific lifetime scoping and registration calls into the container specific way. The cool thing is that as long as you register your dependencies with that approach you can benefit from constructor injection into your message handlers and all your classes implementing one of the automatically scanned interfaces such as (IWantToRunWhenBusStartsAndStops, IManageUnitsOfWork…). It is also possible to use property injection and in fact most NServiceBus examples found on the web use property injection to inject dependencies such as IBus into message handlers.

public class MyHandler : IHandleMessages<Message> {

   public IBus Bus{ get; set; }

   public void Handle(Message msg) { }
}

Now imagine that instead of using the default container abstraction you want to use Ninject as the underlying container (why? because Ninject rocks :D). That is when the container abstraction starts to leak. Waiiit, did I lost you?

Consider a standard example using Ninject with property injection:

public class Foo {
   [Inject]
   public IDependency Dependency { get; set; }
}

If you do property injection with ninject you have to annotate the property with the InjectAttribute. What would this mean for NServiceBus users which migrate existing samples or solutions to NServiceBus with Ninject behind the scenes? Guess what, they would need to declare/annotate each property with the InjectAttribute. Therefore the sample message handler above would look like this:

public class MyHandler : IHandleMessages<Message> {

   [Inject]
   public IBus Bus{ get; set; }

   public void Handle(Message msg) { }
}

When we first started with the NinjectObjectBuilder implementation, we wanted to provide the same experience for NServiceBus users regardless whether they use Ninject as the underlying container or not. That is why the NinjectObjectBuilder implementation uses a specialized Ninject StandardKernel which has a more aggressive injection heuristic (IInjectionHeuristic implementation for those who care), which allows to do property injection without having to declare the InjectAttribute. And now you see the main difference when using Ninject alone or Ninject together with NServiceBus. With Ninject alone, you have to declare the InjectAttribute on dependencies injection into properties: with NServiceBus you don’t.

About the author

Daniel Marbach

4 comments

  • Does NServiceBus expect the container to do implicit property injection? In other words, should properties that can’t be injected (because they are readonly or have an unknown service type) be skipped?

Recent Posts