C# 从ServiceCollection获取IConfiguration
我正在为C# 从ServiceCollection获取IConfiguration,c#,asp.net-core,asp.net-core-2.0,asp.net-core-configuration,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.FirstOrDef
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"));
}
公共静态IServiceCollection AddApi(此IServiceCollection服务)
{
//从集合中获取配置
var configuration=(IConfiguration)services.FirstOrDefault(p=>p.ServiceType==typeof(IConfiguration)).ImplementationInstance;
services.Configure(configuration.GetSection(“数据库”));
}
这是从集合中获取IConfiguration
实例的正确方法,还是有更优雅的解决方案?我不想将IConfiguration实例作为参数添加到方法中。我创建了自己的“服务集合”类型,它包装了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
实例,您可能会发现在服务集合中反复搜索它有点乏味。根据注释,我已将扩展方法更改为:,因此,由应用程序的编写者为我的选项提供配置部分
public static IServiceCollection AddApi(this IServiceCollection services, IConfiguration databaseConfiguration)
{
services.Configure<DatabaseOptions>(databaseConfiguration);
}
以这种方式使用它的决定主要取决于这些评论。在开发许多开发人员使用的组件时,这种方式可能比在应用程序中使用的内部组件更相关
我觉得从任何地方访问IConfiguration都是一个糟糕的设计,除了 在组合根目录(ASP.NET核心的启动类)中,如下所示 表示配置文件必须具有特定的结构 这是根本无法改变的。相反,我将编写一个扩展方法 在组合根目录中配置配置类并传递 IConfiguration对象,类似于 .Configure(Configuration.GetSection(“MyLibConfig”)。 这样,开发人员就可以从您的 组件可以决定在appsettings.json中放置它的位置
或者,当两个库直接连接时,您将如何解决冲突 参考IConfiguration,并在 配置?即JsonSettings,但具有完全不同的结构?它 只有让编写它的开发人员选择 将节名称传递给设置 选项通过。配置
要从
IServiceCollection
获取IConfiguration
,为什么不直接解析依赖项
IConfiguration configuration=services.BuildServiceProvider().GetService();
显式依赖项应该直接注入到需要的地方。否则会使代码产生误导。尽管如此,正如前面所说的,如果直接将其注入到方法中会更好。我认为,从组合根内部以外的任何地方访问IConfiguration
是一种糟糕的设计(Startup
class for ASP.NET core),因为这意味着配置文件必须具有一个根本无法更改的特定结构。相反,我将编写一个扩展方法来配置composition根目录中的配置类,并将一个IConfiguration
对象传递给,类似于.configure(Configuration.GetSection(“MyLibConfig”)
。这样,当两个库直接引用IConfiguration
并在配置中具有相同的部分时(即JsonSettings
但具有完全不同的配置),使用组件编写应用程序的开发人员可以决定将其放置在appsettings.json中的位置,或者如何解决冲突Structure?只有让编写它的开发人员选择并将节名传递给通过设置选项的your扩展方法才能解决此问题。配置对我不起作用,因为实现实例为空。必须调用实现工厂(空)
。可以工作,但当然相当脏。因为这需要构建服务提供商。取决于应用程序的类型和您正在执行的操作,这可能没有什么大不了的。
public void ConfigureServices(IServiceCollection services)
{
services.AddApi(Configuration.GetSection("Database"));
services.AddMvc();
}