Use Dependency Injection To Simplify Application Settings

We've all seen and written code that accesses data from our app.config or web.config file.  We'll throw some simple settings in there:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="enableLogging" value="true" />
        <add key="startDate" value="12/1/2010" />
        <add key="baseFee" value="157.50" />
    </appSettings>
</configuration>

And then we'll use the ConfigurationManager to pull the data out when we need it:

public class Foo
{
    public void DoSomething()
    {
        bool enableLogging = Convert.ToBoolean(ConfigurationManager.AppSettings["enableLogging"]);
        DateTime startDate = Convert.ToDateTime(ConfigurationManager.AppSettings["startDate"]);
        decimal baseFee = Convert.ToDecimal(ConfigurationManager.AppSettings["startingFee"]);
    }
}

Now that Inversion of Control and Dependency Injection are part of my everyday development, I don't do it this way anymore.  It's messy and doesn't allow me to easily plug in different values during testing.

These days, I create a simple interface for my application settings:

public interface IApplicationSettings
{
    bool EnableLogging { get; }
    DateTime StartDate { get; }
    decimal BaseFee { get; }
}

And create an implementation of this interface that pulls data from app.config:

public class AppConfigSettings : IApplicationSettings
{
    public AppConfigSettings()
    {
        this.EnableLogging = Convert.ToBoolean(ConfigurationManager.AppSettings["enableLogging"]);
        this.StartDate = Convert.ToDateTime(ConfigurationManager.AppSettings["startDate"]);
        this.BaseFee = Convert.ToDecimal(ConfigurationManager.AppSettings["startingFee"]);
    }
 
    #region IApplicationSettings Members
 
    public bool EnableLogging { get; private set; }
    public DateTime StartDate  { get; private set; }
    public decimal BaseFee { get; private set; }
 
    #endregion
}

I register my types with my IoC container.  During production, dependency injection takes over and automatically gives me my AppConfigSettings instance.  For testing, I generate a mock IApplicationSettings.  And using these settings just got a whole lot cleaner:

public class Foo
{
    public Foo(IApplicationSettings applicationSettings)
    {
        
    }
}
Published Monday, November 23, 2009 9:51 PM by PSteele
Filed under: , ,

Comments

# re: Use Dependency Injection To Simplify Application Settings

There is a better way: use type converters. Define a class that implements AbstractTypeConverter

and implement the method PerformConversion(string value, Type type) that will read from the Application settings and returns the value.

This is way easier than writing a custom class and is also generic as a bonus!

Tuesday, November 24, 2009 1:34 AM by Ravi Terala

# re: Use Dependency Injection To Simplify Application Settings

Yup, I do exactly the same :)

Tuesday, November 24, 2009 5:25 AM by Damon Stephenson

# re: Use Dependency Injection To Simplify Application Settings

Ravi,

Not familiar with that class from Castle.  Could you provide a code-snippet to show how it would be used in this case?

Tuesday, November 24, 2009 10:41 AM by PSteele

# re: Use Dependency Injection To Simplify Application Settings

Even better, when you end up with many deployed apps sharing similar settings you can now move them all into the database with minimal impact.

Tuesday, November 24, 2009 8:13 PM by Barry Dahlberg

# re: Use Dependency Injection To Simplify Application Settings

Barry -- exactly!

Tuesday, November 24, 2009 9:28 PM by PSteele