You are currently browsing the monthly archive for October 2008.

I saw a post this morning entitled Insidious Dependencies which I recommend reading. It discusses some of the dependencies that creep in often without you realising such as depending on the file system and DateTime (DateTime.Now being the common one). At the bottom of the list is a nod towards configuration also being a dependency when tied directly to settings in web.config/app.config.

This is actually one of my bug bears and my solution to this (with the help of some IoC) is to use a configuration model with a configuration provider ‘pattern’ via an IConfigurationProvider interface like below:

public interface IConfigurationProvider<T>
{
    T GetConfiguration();
}

This then allows you to define a dependency on this interface with T being the configuration model object you are interested in. So for instance, if you have an EmailServer class that would be configured with say server name and port number then you would define an EmailServerConfiguration such as

public class EmailServerConfiguration
{
    public string ServerName;
    public int Port;
}

And then our EmailServerConfiguration would be injected into our EmailServer via our IConfigurationProvider:

public class EmailServer
{
    private readonly EmaiServerConfiguration config;

    public class EmailServer(IConfigurationProvider<EmailServerConfiguration> configProvider)
    {
        config = configProvider.GetConfiguration();
    }
}

By using this approach we are gaining a couple of things. For one we are working to a strong configuration contract rather than directly to app.config settings. I know this can be achieved using the .Net 2.0 settings but we are also gaining this ability without being directly dependent on this so we can directly inject our configuration for testing purposes.

We are also breaking a direct dependency on where we get our configuration from as we can have different implementations of the particular IConfigurationProvider so we can drive our config from app.config, our IoC container, a database or from a web service call all without changing our EmailServer class itself.

For example, our app.config using application settings directly would be something like this:

public class ApplicationSettingsBasedEmailServerConfigurationProvider
    : IConfigurationProvider<EmailServerConfiguration>
{
    public EmailServerConfiguration GetConfiguration()
    {
        EmailServerConfiguration config = new EmailServerConfiguration();
        config.ServerName = ConfigurationManager.AppSettings["EmailServerName"];
        config.Port = Int32.Parse(ConfigurationManager.AppSettings["EmailServerPort"]);
        return config;
    }
}

Whereas a Castle Windsor driven configuration (or any other DI framework) would be:

public class WindsorBasedEmailServerConfigurationProvider
    : IConfigurationProvider<EmailServerConfiguration>
{
    private readonly EmailServerConfiguration config;

    public WindsorBasedEmailServerConfigurationProvider(string emailServerName, int emailServerPort)
    {
        config = new EmailServerConfiguration { ServerName = emailServerName, Port = emailServerPort };
    }

    public EmailServerConfiguration GetConfiguration()
    {
        return config;
    }
} 

I hope from this you can see how easy it is to break the direct dependency on configuration and gain some flexibility in the process.

For this post we are going to enable auto registration in the container and see what benefits it can bring us.

What is auto registration?

What we mean by this is that we would like all our controllers and all the services those controllers depend on (and any dependencies they may have) to be automatically registered into the container for us. This saves us the extra step of manually registering them in the xml configuration.

The ability to auto register components into the container should be available in the last castle release (I haven’t checked to be honest) but what I want to show is the reduced friction way of enabling this. To do this we need to grab one of the later builds of castle.

Getting the latest castle builds

The castle project publishes all builds to http://builds.castleproject.org (which at the time of writing this just happens to be down at the moment which is the first time I’ve ever seen it down). On here you will see all successful and failed builds. If you explore the details of any of these builds you’ll also see a whole load of unit tests that are run as part of the build. This is a practice that I highly recommend following.

For this example I’ve grabbed build 967. Unzip the contents of the build and copy the bin folder contents into your tools/castle directory.

Before running the application there are two slight changes that need to be made. The first one is that when using later builds you will get an error when you navigate to your site with “Could not load type ‘Castle.MonoRail.Framework.EngineContextModule’ from assembly ‘Castle.MonoRail.Framework’“. To fix this, edit the web.config and remove the ‘monorail’ Http Module from the system.web/httpModules section.

The other change is with the windsor integration. A change was made to the windsor extension called RailsFacility which is now called MonoRailFacility instead. Make this change within the facilities.config file.

With these slight changes in place we should be able to now build and run our application.

So now onto the real guts of this post.

What we want to first do is auto register all our controllers. Each of our controllers is ultimately an IController so what we really want to do is auto register all IController classes into the container.

We do this within GlobalApplication.cs (the codebehind for global.asax) within the Application_OnStart method. You’ll already see that this is where the container get’s initialised for the whole application, passing in a new instance of XmlInterpreter with no parameters which tells windsor to look in web.config for the configuration.

public void Application_OnStart()
{
    container = new WindsorContainer(new XmlInterpreter());
}

We then add the following line beneath this to get windsor to automatically register all controllers:

container.Register(
    AllTypes.Of<IController>()
    .FromAssembly(Assembly.GetExecutingAssembly()));

Hmm – a nice bit of fluent interface goodness there. So here we are looking for all types of IController from the executing assembly and registering them into the container.

If we build and run our application everything works as it should but there’s a little gotcha (it’s actually a good gotcha) in that this new line of code won’t do much for us right now as we are still explicitly registering our controllers in the controllers.config file. The container still loads and resolves item in the config files first. When the auto registration code is invoked it will skip over any controllers that have already been explicitly registered manually. This enables us to override the auto registration so we still have flexibility when we need it.

So if we now go into our controllers.config and remove all the existing controller registrations and rerun the application there should be no change and now all our controllers are being auto registered.

If we now run our application then our BookController is still retrieved from the container (as it was auto registered) and the container is still satisfying it’s dependency on the BookRepository (as it is still manually registered).

To get our services (and other components) auto registered we make a further change to GlobalApplication.cs and add the following:

public void Application_OnStart()
{
    container = new WindsorContainer(new XmlInterpreter());
    container.Register(
        AllTypes.Of<IController>()
        .FromAssembly(Assembly.GetExecutingAssembly()));
    container.Register(
        AllTypes.Pick()
        .FromAssembly(Assembly.GetExecutingAssembly())
        .WithService.FirstInterface());
}

Here we’re now selecting all types from the executing assembly (our web app) and registering them into the container. We are also specifying WithService.FirstInterface. What this enables is that for any types that implement an interface, use the first interface as the ‘service’ to register the type against.

If we introduce an IBookRepository interface (something we will do at some point btw) and changed BookRepository to implement this interface then as long as IBookRepository was the first interface BookRepository implemented then it would be registered into the container against that interface.

So if we changed our BookController to depend on IBookRepository then it would all still be auto registered and wired up correctly as we expect.

This is actually one of the great things with using auto registration in that we can make this changes without having to manually change the configuration. It also allows us to add new controllers, again without having to worry about the manual configuration changes. This allows us to focus on coding and providing a solution in a more friction free manner.

Now to test our application. First off, change components.config to remove our manual BookRepository configuration.

As you should see, our application loads and runs as it did before but now with our controllers, services and supporting components all auto registered for us.

Next steps

So far we haven’t explored the benefits of Monorail in regards to unit testing, and we’ve mentioned about introducing IBookRepository which will give us some flexibility to our implementations. I’m intending that one of those implementations will be using NHibernate and we’ll be using Fluent NHibernate to handle our mapping for us. Let’s see if I can pull those out of the bag quicker than I’ve pulled this one out 🙂