具有其他依赖项的 ConfigurationProvider [英] ConfigurationProvider with other dependencies
问题描述
我已经实现了我的自定义 IConfigurationProvider 和 IConfigurationSource.
I've implemented my customs IConfigurationProvider and IConfigurationSource.
public class MyConfigurationSource : IConfigurationSource
{
public string Foo { get; set; }
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new MyConfigurationProvider(this);
}
}
internal class MyConfigurationProvider : ConfigurationProvider
{
public MyConfigurationSource Source { get; };
public MyConfigurationProvider()
{
Source = source
}
public override void Load()
{
// I'd like to assign here my configuration data by using some dependencies
Data = ....
}
}
我在启动构造函数中构建我的配置(我覆盖了由 CreateDefaultBuilder
创建的配置):
I do the build of my Configuration in the Startup constructor (I override the configuration created by CreateDefaultBuilder
):
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables()
.AddMyConfiguration("myfoovalue")
.Build();
扩展方法:
public static IConfigurationBuilder AddMyConfiguration(this IConfigurationBuilder builder, string foo)
{
return builder.Add(new MyConfigurationSource
{
Foo = url
});
}
我希望我能以某种方式注入要在 Load
方法中使用的服务.这里的问题是配置 build
是在 Startup 构造函数中完成的.我只能注入我在这个构造函数中可用的依赖项:IWebHostEnvironment
、IHostEnvironment
、IConfiguration
以及我在构建 WebHost 时添加的所有依赖项.此外,当我调用 AddMyConfiguration
扩展方法时,必须传递这些依赖项.我怎么能使用当时根本不存在的依赖项?
I wish I could somehow inject services to be used in Load
method. The problem here is that the configuration build
is done in the Startup constructor. I can only inject dependencies that I have available in this constructor: IWebHostEnvironment
, IHostEnvironment
, IConfiguration
and all I added when I built the WebHost. Also these dependencies would have to be passed the moment I call the AddMyConfiguration
extension method. How could I use dependencies that don't even exist at that moment?
推荐答案
回答有点晚.
很明显,在 MyConfigurationSource
/MyConfigurationProvider
中,无法使用使用 Startup.ConfigureServices
构建的容器,因为通过调用 ConfigurationBuilder.Build
的时间,ServiceCollection.BuildServiceProvider
还没有被调用.
It's obvious there's no way to use the container, that was built using Startup.ConfigureServices
, in the MyConfigurationSource
/MyConfigurationProvider
simply because by the time ConfigurationBuilder.Build
is invoked, ServiceCollection.BuildServiceProvider
has not been invoked.
一个典型的解决方法是创建另一个具有所需配置的 IServiceProvider
实例,并在 MyConfiguration...
中使用它.
A typical workaround would be to create another instance of IServiceProvider
with required configuration and use it inside MyConfiguration...
.
类似的东西
internal class MyConfigurationProvider : ConfigurationProvider
{
public MyConfigurationSource Source { get; };
public MyConfigurationProvider()
{
Source = source;
ServiceProvider = BuildServiceProvider();
}
public override void Load()
{
// I'd like to assign here my configuration data by using some dependencies
Data = ServiceProvider.GetRequiredService<IMyService>().GetData();
}
protected virtual void ConfigureServices(IServiceCollection services)
{
services.AddMyService();
// etc.
}
private IServiceProvider BuildServiceProvider()
{
var services = new ServiceCollection();
ConfigureServices(services);
return services.BuildServiceProvider();
}
}
但这可能并不总是合适的,所以我也会考虑直接设置值(虽然我没有找到任何关于这种方法有多好的官方信息)
but this might not always be appropriate so I would also consider setting the value directly (though I didn't find any official information about how good this approach is)
public class Startup
{
public void Configure(IApplicationBuilder app)
{
...
app.SetupMyConfiguration();
...
}
}
...
public static class ApplicationBuilderExtensions
{
public static IApplicationBuilder SetupMyConfiguration(this IApplicationBuilder app)
{
var configuration = app
.ApplicationServices
.GetRequiredService<IConfiguration>(); // alternatively IOptions<MyOptions>
var myService = app
.ApplicationServices
.GetRequiredService<IMyService>();
configuration["MyKey"] = myService.GetData("MyKey");
}
}
这篇关于具有其他依赖项的 ConfigurationProvider的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!