asp.net core 動態更新 appsetting.json方法


如何將值更新到appsetting.json?

 

我正在使用官方文檔中IOptions描述的模式.

當我從中讀取值時appsetting.json,這可以正常工作,但是如何更新值並將更改保存回來appsetting.json

在我的例子中,我有幾個字段可以從用戶界面編輯(由管理員用戶在應用程序中).因此,我正在尋找通過選項訪問器更新這些值的理想方法.

 

Matze..  32

 

在編寫此答案時,似乎沒有Microsoft.Extensions.Options包提供的組件具有將配置值寫回的功能appsettings.json.

在我的一個ASP.NET Core項目中,我想讓用戶更改一些應用程序設置 - 這些設置值應該appsettings.json更准確地存儲在可選appsettings.custom.json文件中,如果存在,則會添加到配置中.

像這樣...

public Startup(IHostingEnvironment env) { IConfigurationBuilder builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile("appsettings.custom.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables(); this.Configuration = builder.Build(); } 

我宣布IWritableOptions<T>擴展的接口IOptions<T>; 這樣我就可以替代IOptions<T>IWritableOptions<T>每當我想讀寫設置.

public interface IWritableOptions<out T> : IOptions<T> where T : class, new() { void Update(Action<T> applyChanges); } 

此外,我想出了IOptionsWriter一個組件,旨在用於IWritableOptions<T>更新配置部分.這是我對前面提到的接口的實現......

class OptionsWriter : IOptionsWriter { private readonly IHostingEnvironment environment; private readonly IConfigurationRoot configuration; private readonly string file; public OptionsWriter( IHostingEnvironment environment, IConfigurationRoot configuration, string file) { this.environment = environment; this.configuration = configuration; this.file = file; } public void UpdateOptions(Action<JObject> callback, bool reload = true) { IFileProvider fileProvider = this.environment.ContentRootFileProvider; IFileInfo fi = fileProvider.GetFileInfo(this.file); JObject config = fileProvider.ReadJsonFileAsObject(fi); callback(config); using (var stream = File.OpenWrite(fi.PhysicalPath)) { stream.SetLength(0); config.WriteTo(stream); } this.configuration.Reload(); } } 

由於編寫器不知道文件結構,我決定將段處理為JObject對象.訪問者嘗試查找請求的部分並將其反序列化為實例T,使用當前值(如果未找到),或者僅創建新實例(T如果當前值為)null.然后將此持有者對象傳遞給調用者,調用者將對其應用更改.比更改的對象轉換回JToken將要替換該部分的實例...

class WritableOptions<T> : IWritableOptions<T> where T : class, new() { private readonly string sectionName; private readonly IOptionsWriter writer; private readonly IOptionsMonitor<T> options; public WritableOptions( string sectionName, IOptionsWriter writer, IOptionsMonitor<T> options) { this.sectionName = sectionName; this.writer = writer; this.options = options; } public T Value => this.options.CurrentValue; public void Update(Action<T> applyChanges) { this.writer.UpdateOptions(opt => { JToken section; T sectionObject = opt.TryGetValue(this.sectionName, out section) ? JsonConvert.DeserializeObject<T>(section.ToString()) : this.options.CurrentValue ?? new T(); applyChanges(sectionObject); string json = JsonConvert.SerializeObject(sectionObject); opt[this.sectionName] = JObject.Parse(json); }); } } 

最后,我實現了一個擴展方法,IServicesCollection允許我輕松配置可寫選項訪問器...

static class ServicesCollectionExtensions { public static void ConfigureWritable<T>( this IServiceCollection services, IConfigurationRoot configuration, string sectionName, string file) where T : class, new() { services.Configure<T>(configuration.GetSection(sectionName)); services.AddTransient<IWritableOptions<T>>(provider => { var environment = provider.GetService<IHostingEnvironment>(); var options = provider.GetService<IOptionsMonitor<T>>(); IOptionsWriter writer = new OptionsWriter(environment, configuration, file); return new WritableOptions<T>(sectionName, writer, options); }); } } 

哪個可以用在ConfigureServices......

services.ConfigureWritable<CustomizableOptions>(this.Configuration, "MySection", "appsettings.custom.json"); 

在我的Controller課程中,我可以要求一個IWritableOptions<CustomizableOptions>具有相同特征的實例IOptions<T>,但也允許更改和存儲配置值.

private IWritableOptions<CustomizableOptions> options;

...

this.options.Update((opt) => { opt.SampleOption = "..."; }); 

 


ceferrari..  30

 

簡化版Matze的答案:

public interface IWritableOptions<out T> : IOptionsSnapshot<T> where T : class, new() { void Update(Action<T> applyChanges); } public class WritableOptions<T> : IWritableOptions<T> where T : class, new() { private readonly IHostingEnvironment _environment; private readonly IOptionsMonitor<T> _options; private readonly string _section; private readonly string _file; public WritableOptions( IHostingEnvironment environment, IOptionsMonitor<T> options, string section, string file) { _environment = environment; _options = options; _section = section; _file = file; } public T Value => _options.CurrentValue; public T Get(string name) => _options.Get(name); public void Update(Action<T> applyChanges) { var fileProvider = _environment.ContentRootFileProvider; var fileInfo = fileProvider.GetFileInfo(_file); var physicalPath = fileInfo.PhysicalPath; var jObject = JsonConvert.DeserializeObject<JObject>(File.ReadAllText(physicalPath)); var sectionObject = jObject.TryGetValue(_section, out JToken section) ? JsonConvert.DeserializeObject<T>(section.ToString()) : (Value ?? new T()); applyChanges(sectionObject); jObject[_section] = JObject.Parse(JsonConvert.SerializeObject(sectionObject)); File.WriteAllText(physicalPath, JsonConvert.SerializeObject(jObject, Formatting.Indented)); } } public static class ServiceCollectionExtensions { public static void ConfigureWritable<T>( this IServiceCollection services, IConfigurationSection section, string file = "appsettings.json") where T : class, new() { services.Configure<T>(section); services.AddTransient<IWritableOptions<T>>(provider => { var environment = provider.GetService<IHostingEnvironment>(); var options = provider.GetService<IOptionsMonitor<T>>(); return new WritableOptions<T>(environment, options, section.Key, file); }); } } 

用法:

services.ConfigureWritable<MyOptions>(Configuration.GetSection("MySection")); 

然后:

private readonly IWritableOptions<MyOptions> _options; public MyClass(IWritableOptions<MyOptions> options) { _options = options; } 

要將更改保存到文件:

_options.Update(opt => { opt.Field1 = "value1"; opt.Field2 = "value2"; }); 

並且您可以將自定義json文件作為可選參數傳遞(默認情況下它將使用appsettings.json):

services.ConfigureWritable<MyOptions>(Configuration.GetSection("MySection"), "appsettings.custom.json"); 

 

  • 我不太確定“ MyOptions”,但是閱讀此內容有助於我弄清楚。https://codingblast.com/asp-net-core-configuration-reloading-binding-injecting/ (2認同)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM