简体   繁体   中英

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.

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.

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? ie 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

要从IServiceCollection获取IConfiguration为什么不解决依赖关系?:

IConfiguration configuration = services.BuildServiceProvider().GetService<IConfiguration>();

I created my own "service collection" type which wrapped the IServiceCollection and IConfiguration and all my modules use that type to register their services. For example:

public interface IMyServiceCollection
{
    public IServiceCollection Services { get; set; }

    public IConfiguration Configuration { get; set; }
}

public static void AddFooModule(this IMyServiceCollection myServices)
{
    var services = myServices.Services;
    var config = myServices.Configuration;
}

Then you have to create an extension method with the configuration instance as parameter which creates the implementation for IMyServiceCollection , such as:

public static IMyServiceCollection CreateServiceCollection(this IServiceCollection services, IConfiguration config)
{
    return new MyServiceCollection 
    { 
        Services = services,
        Configuration = config
    };
}

Note that we are using this in a modular framework. For simple applications this is overkill.

I think that your solution is fine as well. But if you need access to the IConfiguration instance frequently you might find searching for it in the service collection over and over a bit tedious.

Docs say that you should require the user to provide you with the appropriate IConfiguration:

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

    return services;
}

You'll need the package Microsoft.Extensions.Options.ConfigurationExtensions for this to work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM