Search code examples
c#asp.net-coreasp.net-core-2.0asp.net-core-configuration

Getting IConfiguration from ServiceCollection


I´m writing my own extension method for ServiceCollection to registered the types of my module and I need to access the IConfiguration instance from the collection to register my Options.

Extension method

public static IServiceCollection AddApi(this IServiceCollection services)
{
  // Get configuration from collection
  var configuration = (IConfiguration) services.FirstOrDefault(p => p.ServiceType == typeof(IConfiguration)).ImplementationInstance;

  services.Configure<DatabaseOptions>(configuration.GetSection("Database"));
}

Is this the right way to get the IConfiguration instance from the collection or is there a more elegant solution? I do not want to add the IConfiguration instance as parameter to the method.


Solution

  • According to the comments I have changed my extension method to the following, so that it is up to the composer of the application to provide the config section for my options.

    public static IServiceCollection AddApi(this IServiceCollection services, IConfiguration databaseConfiguration)
    {  
      services.Configure<DatabaseOptions>(databaseConfiguration);
    }
    

    from the StartUp class, the call looks like

    public void ConfigureServices(IServiceCollection services)
    {
      services.AddApi(Configuration.GetSection("Database"));
      services.AddMvc();
    }
    

    The decision to use it this way are mostly by these comments. This way maybe more relevant, when developing components that are use by many developers than for an internal component you use in your application. Also there is Official docs guidance explaining the same approach

    Imho it's a bad design to access IConfiguration from anywhere except inside the composition root (Startup class for ASP.NET core), as this implies that the configuration file must have a specific structure which can't be changed at all. Instead, I'd write an extension method to configure the config classes inside the composition root and pass a IConfiguration object to, similar to how .Configure(Configuration.GetSection("MyLibConfi‌​g"). This way the developer who composes his application from your components can decide where to place it within the appsettings.json

    Or how would you solve conflicts, when two libraries directly reference the IConfiguration and have the same section within the config? i.e. JsonSettings but have completely different structure? It can only be solved by letting the developer who compose it choose and pass the section name to the your extension method which sets up the options via .Configure