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.

Advertisements