Integrating Your IOC Container With Agatha
Posted by Davy Brion on November 28th, 2009
Agatha relies on the presence of an IOC container, both client-side as well as server-side. When it was still a closed-source library used by my company, we could get away with using our preferred IOC container (Castle Windsor) directly. Obviously, when making an open-source library available you want your users to have the ability to not only use their preferred container, but to integrate with their container as well. With ‘integrate’ i mean that it should be possible to register Agatha’s components in your container, so that you can easily resolve Agatha components (such as the IRequestDispatcher or the IAsyncRequestDispatcher), or to have the ability to have the container automatically inject your dependencies (which are registered in your container) in your Request Handlers (which are resolved and used by Agatha).
I originally planned to use the Common Service Locator project for this, because the project description certainly seemed to fit my need:
The Common Service Locator library contains a shared interface for service location which application and framework developers can reference. The library provides an abstraction over IoC containers and service locators. Using the library allows an application to indirectly access the capabilities without relying on hard references. The hope is that using this library, third-party applications and frameworks can begin to leverage IoC/Service Location without tying themselves down to a specific implementation.
Unfortunately, the shared interface defined in this project only contains method for resolving components. I really wanted to avoid having an Agatha-user be responsible for the correct registration of each component in their container, so the Common Service Locator project doesn’t really offer me any benefits. Instead, i defined my own IContainer interface in Agatha which looks like this:
public interface IContainer { void Register(Type componentType, Type implementationType, Lifestyle lifeStyle); void Register<TComponent, TImplementation>(Lifestyle lifestyle); void RegisterInstance(Type componentType, object instance); void RegisterInstance<TComponent>(TComponent instance); TComponent Resolve<TComponent>(); object Resolve(Type componentType); void Release(object component); }
This interface enables me to perform automatic registration of all of the required components, and whenever Agatha needs to resolve components it will also do so through an instance which implements this interface. We currently have two specific implementations of this interface: one for Castle Windsor, the other for Unity. I’m going to cover how these implementations work later on in this post (as it will be useful to anyone who wants to use another IOC container together with Agatha) but first i want to show how Agatha will either obtain a reference to your container, or instantiate its own container if you don’t give it a container instance.
Agatha has two configuration classes: ServiceLayerConfiguration and ClientConfiguration. ServiceLayerConfiguration defines the following constructors:
public ServiceLayerConfiguration(Assembly requestHandlersAssembly, Assembly requestsAndResponsesAssembly, IContainer container) { // not relevant to this post, so i'm skipping this } public ServiceLayerConfiguration(Assembly requestHandlersAssembly, Assembly requestsAndResponsesAssembly, Type containerImplementation) { // not relevant to this post, so i'm skipping this }
And ClientConfiguration defines the following ones:
public ClientConfiguration(Assembly requestsAndResponsesAssembly, IContainer container) { // not relevant to this post, so i'm skipping this } public ClientConfiguration(Assembly requestsAndResponsesAssembly, Type containerImplementation) { // not relevant to this post, so i'm skipping this }
As you can see, you can pass either an instance of an object that implements Agatha’s IContainer interface, or you can just pass in the type of the IContainer implementation. If you pass in an instance, Agatha will simply reuse that instance for both the registration and the resolving of components. If you pass a type instead of an instance, Agatha will create its own instance and use that for the registration and resolving of components.
Now, how do you integrate your own container? Quite simple, just create a type which implements the IContainer interface and pass an instance of that type to Agatha’s configuration objects. As an example, i’ll show how i did it for Castle Windsor. I created a new assembly called Agatha.Castle which contains the following Container class:
using System; using Agatha.Common.InversionOfControl; using Castle.MicroKernel.Registration; using Castle.Windsor; namespace Agatha.Castle { public class Container : IContainer { private readonly IWindsorContainer windsorContainer; public Container() : this(new WindsorContainer()) {} public Container(IWindsorContainer windsorContainer) { this.windsorContainer = windsorContainer; } public void Register(Type componentType, Type implementationType, Lifestyle lifeStyle) { var registration = Component.For(componentType).ImplementedBy(implementationType); windsorContainer.Register(AddLifeStyleToRegistration(lifeStyle, registration)); } public void Register<TComponent, TImplementation>(Lifestyle lifestyle) { Register(typeof(TComponent), typeof(TImplementation), lifestyle); } public void RegisterInstance(Type componentType, object instance) { windsorContainer.Register(Component.For(componentType).Instance(instance)); } public void RegisterInstance<TComponent>(TComponent instance) { RegisterInstance(typeof(TComponent), instance); } public TComponent Resolve<TComponent>() { return windsorContainer.Resolve<TComponent>(); } public object Resolve(Type componentType) { return windsorContainer.Resolve(componentType); } public void Release(object component) { windsorContainer.Release(component); } private static ComponentRegistration<TInterface> AddLifeStyleToRegistration<TInterface>(Lifestyle lifestyle, ComponentRegistration<TInterface> registration) { if (lifestyle == Lifestyle.Singleton) { registration = registration.LifeStyle.Singleton; } else if (lifestyle == Lifestyle.Transient) { registration = registration.LifeStyle.Transient; } else { throw new ArgumentOutOfRangeException("lifestyle", "Only Transient and Singleton is supported"); } return registration; } } }
The Agatha.Castle.Container class defines two constructors. One is the default constructor, which will create a new instance of the Windsor container, and the other requires you to pass an instance to a Windsor container. The rest of the type simply implements Agatha’s IContainer interface methods and delegates to the real container instance. If you pass an instance of the Agatha.Castle.Container class to Agatha’s ServiceLayerConfiguration class, Agatha will use this type to register and resolve all components. Which means it either reuses your container instance, or creates its own if you don’t pass one (which i’d only recommend if you’re not using an IOC container in your code). This makes it pretty easy to integrate whatever IOC container you want to use.
Agatha currently has ‘out-of-the-box’ support for Castle Windsor and Microsoft’s Unity. If you want to use your own container, you now know how easily you can integrate it with Agatha. And i’d be very happy to accept patches which add more Agatha.YourPreferredContainer assemblies

November 29th, 2009 at 10:48 pm
This is exactly how we do it in NServiceBus, perhaps is time for a “Common Service Configuration” project
Anyways, interesting posts. Good luck with Agatha!
November 29th, 2009 at 10:54 pm
@Andreas
glad to know other people are using this approach as well… while i was working on this i couldn’t help think “i can’t be the only one who wants to do it like _this_”
January 15th, 2010 at 8:04 am
[...] be a need to have a common interface that offers such additional functionality; Davy Brion’s Agatha project does [...]
February 21st, 2010 at 8:38 pm
[...] as its IoC container, but it’s been changed to support multiple containers in a similar manner as Agatha does it. Agatha however, was originally developed with Castle Windsor as its IoC container, and as [...]