Search code examples
c#simple-injector

Injecting configuration objects in a .NET application


I'm reviewing a code I wrote sometime before and I noticed I did in past

  public class Linq2DbSettings : ILinqToDBSettings
{
    public IEnumerable<IDataProviderSettings> DataProviders
    {
        get { yield break; }
    }

    public string DefaultConfiguration =>
        "SqlServer"; // lets set your configuration as default, so you can call just new DataContext() or new DataConnection()

    public string DefaultDataProvider => ProviderName.SqlServer; // and set default database type


    public IEnumerable<IConnectionStringSettings> ConnectionStrings
    {
        get
        {
            yield return
                new ConnectionStringSettings
                {
                    Name = "SqlServer",
                    ProviderName = "SqlServer",
                    ConnectionString =ConfigurationManager.ConnectionStrings["default"].ConnectionString
                };
        }
    }
}

public class ConnectionStringSettings : IConnectionStringSettings
{
    public string ConnectionString { get; set; }
    public string Name { get; set; }
    public string ProviderName { get; set; }
    public bool IsGlobal => false;
}

Even if it's related to Linq2Db it appies to all classes where I need to resolve the container.

As you can see I'm using here ConfigurationManager.ConnectionStrings["default"] while it would be best to use IConfiuration from Microsoft.Extensions.Configuration

To do so I should resolve the IConfiguration item, registered in SimpleInjector's Container.

In past I used a wrapper

public static class ContainerWrapper
{
    public static Container Container { get; set; }
}

and I assigned it as

    ContainerWrapper.Container = container;

    container.Verify();

But I think it's a wrong approach, what's the best solution?


Solution

  • My advise is the following:

    • Keep your configuration objects narrow; don't create wide configuration objects that contain a large set of propertiesand are used by many consumers.
    • Prevent configuration objects from reading from the configuration system. Make them immutable behaviorless data objects instead, and supply them with configuration values in their constructor. This prevents the configuration object from becoming a Volatile Dependency.
    • Remove the interfaces on your configuration objects. Interfaces are meant to hide behavior, but the configuration objects should only contain data.
    • Load configuration values during application startup, and register those configuration objects as Singleton in the container.