从ServiceCollection获取IConfiguration

Jeh*_*hof 11 c# asp.net-core asp.net-core-2.0 asp.net-core-configuration

我正在编写自己的扩展方法ServiceCollection来注册模块的类型,我需要IConfiguration从集合中访问实例来注册我的选项.

扩展方法

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"));
}
Run Code Online (Sandbox Code Playgroud)

这是IConfiguration从集合中获取实例的正确方法还是有更优雅的解决方案?我不想将IConfiguration实例作为参数添加到方法中.

Jeh*_*hof 9

根据评论,我已将扩展方法更改为以下内容,以便应用程序的编写者为我的选项提供配置部分。

public static IServiceCollection AddApi(this IServiceCollection services, IConfiguration databaseConfiguration)
{  
  services.Configure<DatabaseOptions>(databaseConfiguration);
}
Run Code Online (Sandbox Code Playgroud)

从 StartUp 类,调用看起来像

public void ConfigureServices(IServiceCollection services)
{
  services.AddApi(Configuration.GetSection("Database"));
  services.AddMvc();
}
Run Code Online (Sandbox Code Playgroud)

以这种方式使用它的决定主要是这些评论。在开发许多开发人员使用的组件时,这种方式可能更相关,而不是在应用程序中使用的内部组件。

恕我直言,从组合根内部(ASP.NET 核心的启动类)之外的任何地方访问 IConfiguration 是一个糟糕的设计,因为这意味着配置文件必须具有根本无法更改的特定结构。相反,我会编写一个扩展方法来配置组合根目录中的配置类,并将 IConfiguration 对象传递给,类似于 .Configure(Configuration.GetSection("MyLibConfi??g")。这样,编写他的开发人员您的组件中的应用程序可以决定将其放置在 appsettings.json 中的什么位置

或者当两个库直接引用 IConfiguration 并且在配置中具有相同的部分时,您将如何解决冲突?即 JsonSettings 但具有完全不同的结构?它只能通过让组成它的开发人员选择并将部分名称传递给您的扩展方法来解决,该方法通过 .Configure 设置选项


byt*_*dev 7

要获得IConfigurationIServiceCollection为什么不解决?:依赖

IConfiguration configuration = services.BuildServiceProvider().GetService<IConfiguration>();
Run Code Online (Sandbox Code Playgroud)

  • 因为这需要构建服务提供者。 (2认同)

Hen*_*ema 5

我创建了自己的“服务集合”类型,它包装了IServiceCollectionIConfiguration我的所有模块都使用该类型来注册他们的服务。例如:

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;
}
Run Code Online (Sandbox Code Playgroud)

然后,您必须使用配置实例作为参数创建一个扩展方法,该方法创建 for 的实现IMyServiceCollection,例如:

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

请注意,我们在模块化框架中使用它。对于简单的应用程序,这是矫枉过正。

我认为你的解决方案也很好。但是,如果您需要IConfiguration经常访问该实例,您可能会发现在服务集合中一遍又一遍地搜索它有点乏味。