稍后在程序中添加到.NET核心配置



这是我为.NET核心应用程序设置的

public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.ConfigureAppConfiguration((builderContext, config) =>
{
var entryAssemblyFolder = new FileInfo(Assembly.GetEntryAssembly().Location).DirectoryName;
IHostingEnvironment env = builderContext.HostingEnvironment;
config
.SetBasePath(entryAssemblyFolder)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.UseStartup<Startup>()
.Build();
}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public static IConfiguration Configuration { get; set; }
}

当程序启动时,以上所有操作都会运行。在程序执行的稍后时间点,我希望能够根据启动时未知的数据添加额外的配置。以下是伪代码,因为ConfigurationBuilder构造函数没有参数:

public class Helper
{
public void Add(string key, string value)
{
//pseudo-code:
var builder = new ConfigurationBuilder(Startup.Configuration);  
builder.AddInMemoryCollection(new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>(key, value)
});
Startup.Configuration = builder.Build();
}
}

如何在保留现有配置的同时将其添加到现有配置中(包括reloadOnChange:true(?

谢谢,

我对MemoryConfigurationProvider的来源做了更多的挖掘。提供程序将初始数据复制到自己的data属性中。

因此,即使更新了原始字典,提供程序在初始化时仍然只有原始值。

还没有尝试过GetReloadToken方法,它可能会起作用,但这里有一种更直接的替代方法。

假设这是您的配置:

public class MyConfiguration
{
public static Dictionary<string,string> InMemoryCollection =
new Dictionary<string, string>
{
{"InMemoryCollection:Option1", "value1"},
{"InMemoryCollection:Option2", "value2"}
};
}

初始化您的配置:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(builder => {
builder.AddInMemoryCollection(MyConfiguration.InMemoryCollection);
})
.UseStartup<Startup>();

假设您有一个控制器来读取并输入新值:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private IConfigurationRoot configuration;
/// <summary>
/// Initializes a new instance of the <see cref="ValuesController"/> class.
/// Value injected through DI.
/// </summary>
/// <param name="configuration">The configuration.</param>
public ValuesController(IConfiguration configuration)
{
this.configuration = (IConfigurationRoot)configuration;
}
[HttpGet]
/// <summary>
/// Get in memory values.
/// </summary>
/// <returns></returns>
public IDictionary<string,string> Get()
{
var result = new Dictionary<string, string>();
this.configuration.GetSection("InMemoryCollection").Bind(result);
return result;
}
[HttpPost]
/// <summary>
/// Enter a new value.
/// </summary>
/// <param name="value">The value.</param>
public void Post([FromBody] string value)
{
//get the provider instance from the configuration root.
MemoryConfigurationProvider memoryProvider =
(MemoryConfigurationProvider)this.configuration.Providers
.First(p =>
p.GetType() == typeof(MemoryConfigurationProvider));
//add the new option into the providers data collection.
var nextKey = MyConfiguration.InMemoryCollection.Count + 1;
memoryProvider.Add(
$"InMemoryCollection:Option{nextKey}",
value);
}
}

注意:我不知道动态添加的配置选项的详细信息/要求,但使用AddInMemoryCollection方法似乎不是最好的选择。当然,除非你故意不想坚持下去。不过,我可以肯定,还有其他方法/解决方案可以解决这个问题,而不必使用Microsoft.Extension.Configuration API。

最新更新