具有其他依赖项的 ConfigurationProvider [英] ConfigurationProvider with other dependencies

查看:33
本文介绍了具有其他依赖项的 ConfigurationProvider的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现了我的自定义 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 构造函数中完成的.我只能注入我在这个构造函数中可用的依赖项:IWebHostEnvironmentIHostEnvironmentIConfiguration 以及我在构建 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆