SimpleInjector and Rebus

Sep 27, 2014 at 8:26 PM
hi,

I'm currently working with Rebus as my ServiceBus implementation. It has a built in SimpleInjector Adapter that I'm using as well. It seems to work ok, but I have a question about Disposing the container. In most of the samples in the Rebus documentation the container gets Disposed at the end in order to properly Dispose of the Bus. SimpleInjector, of course, does not implement Dispose, so how can I properly Dispose of the Bus?

The relevant code for the Rebus implementation of SimpleInjector container adaptor is here (https://github.com/rebus-org/Rebus/blob/master/src/Rebus.SimpleInjector/SimpleInjectorAdapter.cs).

What I did to get around this was to implement IDisposable on my SimpleInjectorAdapter. Then when my application/service stops I can call Dispose on the Adapter. This is essentially what I would do if I was using a container that supported IDisposable but I'm wondering; am I missing something in not disposing the container directly? More importantly, how can I make sure my other Singleton objects in the container are getting disposed of as well (e.g. RavenDB DocumentStore)?
Coordinator
Sep 27, 2014 at 8:52 PM
Edited Sep 28, 2014 at 10:29 AM
The reason that the Simple Injector Container doesn't implement IDisposable is because of two reasons:
  1. most disposable components in your registration will have a scope lifestyle and those will get disposed when the scope ends. So the number of singleton components should be very low.
  2. Since there will usually be one container instance for the duration of the application, singleton instances will live for the same time. When the app domain gets unloaded, the CLR makes sure that finalizers are called, to make sure that unmanaged resources get freed.
So the idea is that for the few times you need to do dispose, you can do it manually. Although this reasoning is quite reasonable, it doesn't always work that way, because:
  1. In some scenarios users create multiple container instances that not live for the duration of the application (not a very common scenario though).
  2. Sometimes the Dispose methods of components do a bit more than free up unmanaged resources and since the CLR never calls Dispose methods (just finalizers).
  3. In general, this goes against the idea of resource management, where the one who creates and manages an instance, is also responsible of disposing it.
So we're considering the addition of a Dispose method for version 3. But that work item also contains a comment for a workaround to add this behavior for the current version:
// when application starts
var globalScope = new Scope();
var container = new Container();
 
// Register an initializer that stores instances for disposal, and gets hooked to Singleton 
// registrations who's implementation type implements IDisposable.
container.RegisterInitializer(
    data => globalScope.RegisterForDisposal((IDisposable)data.Instance), 
    context => context.Producer.Lifestyle == Lifestyle.Singleton && 
        typeof(IDisposable).IsAssignableFrom(context.Registration.ImplementationType));
 
// when application ends
globalScope.Dispose();
This code snippet registers a delegate that gets hooks to the creation of every singleton component who's implementation type implements IDisposable. The created instance is stored in the globalScope and this scope can be disposed when the application ends. By changing the supplied predicate, you can limit the number of registrations where this delegate gets hooked to, if needed.
Marked as answer by dot_NET_Junkie on 9/28/2014 at 3:36 AM
Sep 28, 2014 at 3:37 PM
Thank you Steven for your, as usual, extensive answer and education. One of these days I'm going to learn not to ask question here and walk away from the computer. :)