Integrating Your IOC Container With Agatha
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:
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:
And ClientConfiguration defines the following ones:
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:
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 :)
Written by Davy Brion, published on 2009-11-28 18:59:03
comments powered by Disqus