26

我正在编写自己的扩展方法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"));
}

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

4

3 回答 3

9

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

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

从 StartUp 类,调用看起来像

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

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

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

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

于 2017-08-21T07:34:17.510 回答
8

从为什么不解决依赖关系?IConfigurationIServiceCollection

IConfiguration configuration = services.BuildServiceProvider().GetService<IConfiguration>();
于 2020-06-18T09:22:33.973 回答
6

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

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;
}

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

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

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

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

于 2017-08-18T07:58:50.720 回答