Skip to content
Mogens Heller Grabe edited this page Nov 28, 2013 · 7 revisions

Unless you're working with Rebus in one-way client mode (as described on Different bus modes), Rebus will be receiving messages and will at some point need to obtain a message handler instance to handle a message.

Rebus will do that by asking the IActivateHandlers abstraction for handlers for the incoming message, and this is usually where you would use an implementation of IActivateHandlers that wraps an IoC container, a so-called "container adapter", to create the handler instances by delegating the instantiation to the IoC container.

This way, handlers can have dependencies injected, instance lifetimes managed, etc.

In order to configure Rebus to use a container adapter, include the NuGet package of the container of your choice (e.g. Rebus.Castle.Windsor) and go

Configure.With(new WindsorContainerAdapter(container))
    .(...)

This will do the following two things:

  1. Pass the container adapter to Rebus, thus delegating handler instantiation to the container.
  2. Put the resulting IBus instance into the container with a singleton lifestyle, ensuring that the bus is disposed when the container is disposed.

When your application shuts down

When your application shuts down, you would have done this anyway:

container.Dispose();

Just keep doing it, because the container adapter ensures that the IBus instance is registered in a way that disposes the bus properly when the container is disposed, allowing currently executing handlers to finish gracefully, etc.

The Rebus philosophy

At some point, Rebus had a registration API for automatically picking up and registering handlers in the container, but it was extremely hard to normalize the behavior across all the available IoC containers. Therefore: you're on your own when it comes to registering handlers.

It shouldn't be too hard, though - I'm not an expert on all IoC containers, but with Castle Windsor you'd usually be satisfied doing something like this:

container.Register(Classes.FromAssemblyContaining<SomeHandler>()
                      .BasedOn<IHandleMessages>()
                      .WithServiceAllInterfaces()
                      .LifestyleTransient());

in order to automagically pick up all Rebus handlers from one particular assembly.

A word of warning, though

When you're working with sagas and you have multiple worker threads, it is important that your handlers have a transient lifestyle! In other words, it is important that every incoming message will result in a fresh handler instance.

This is because of the Data property on the handler - this is where the current saga instance will be put, and if your handler instance is a singleton it will be shared between threads, most likely leading to the hardest-to-track-down bugs you'll ever not track down.

You know what? Just forget about the "when this and when that" I said above - just make sure, always, that your handlers are registered with a transient lifestyle! - in general, transient lifestyle is a better default for IoC container components, and that is a fact.

Clone this wiki locally