【问题标题】:ConfigurationProvider with other dependencies具有其他依赖项的 ConfigurationProvider
【发布时间】:2020-09-16 16:40:43
【问题描述】:

我已经实现了我的自定义 IConfigurationProvider 和 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 = .... 
    }
}

我在 Startup 构造函数中构建我的配置(我覆盖了 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 扩展方法时,也必须传递这些依赖项。我怎么能使用当时甚至不存在的依赖项?

【问题讨论】:

    标签: c# .net-core dependency-injection configuration


    【解决方案1】:

    回答有点晚了。

    很明显,在MyConfigurationSource/MyConfigurationProvider 中无法使用使用Startup.ConfigureServices 构建的容器,因为在调用ConfigurationBuilder.Build 时,还没有调用ServiceCollection.BuildServiceProvider

    典型的解决方法是创建另一个具有所需配置的IServiceProvider 实例并在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();
        }
    }
    

    但这可能并不总是合适的,所以我也会考虑直接设置值(虽然我没有找到任何关于这种方法有多好的官方信息)

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

    【讨论】:

      猜你喜欢
      • 2011-02-21
      • 1970-01-01
      • 2014-03-22
      • 2014-12-09
      • 1970-01-01
      • 2014-07-01
      • 2013-04-17
      • 1970-01-01
      • 2014-01-22
      相关资源
      最近更新 更多