Asp.net core 手动触发IOptionsMonitor<>;。一旦改变
在ASP.NET Core 2.1中,我使用IOptionsMonitor并对其进行设置,以便在更改appSettings.json文件时成功获取事件。所以这是有效的 我现在想做的是,通过代码手动更改选项中的一些值,并触发所有监视器。这可能吗?对于Asp.net core 手动触发IOptionsMonitor<>;。一旦改变,asp.net-core,configuration,settings,Asp.net Core,Configuration,Settings,在ASP.NET Core 2.1中,我使用IOptionsMonitor并对其进行设置,以便在更改appSettings.json文件时成功获取事件。所以这是有效的 我现在想做的是,通过代码手动更改选项中的一些值,并触发所有监视器。这可能吗?对于IOptionsMonitor,它只会更改内存中的值,而不会保存回appsettings.json。为了解决这个问题,您需要实现自己的方法将更改保存回appsettings.json 定义从IOptions继承的IWritableOptions pu
IOptionsMonitor
,它只会更改内存中的值,而不会保存回appsettings.json
。为了解决这个问题,您需要实现自己的方法将更改保存回appsettings.json
- 定义从
IOptions继承的
IWritableOptions
public interface IWritableOptions<out T> : IOptions<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 IConfigurationRoot _configuration; private readonly string _section; private readonly string _file; public WritableOptions( IHostingEnvironment environment, IOptionsMonitor<T> options, IConfigurationRoot configuration, string section, string file) { _environment = environment; _options = options; _configuration = configuration; _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)); _configuration.Reload(); } }
- 配置
IWritableOptions
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 configuration = (IConfigurationRoot)provider.GetService<IConfiguration>(); var environment = provider.GetService<IHostingEnvironment>(); var options = provider.GetService<IOptionsMonitor<T>>(); return new WritableOptions<T>(environment, options, configuration, section.Key, file); }); } }
- 使用
public class OptionsController : Controller { private readonly IWritableOptions<Locations> _writableLocations; public OptionsController(IWritableOptions<Locations> writableLocations) { _writableLocations = writableLocations; } public IActionResult Change(string value) { _writableLocations.Update(opt => { opt.Name = value; }); return Ok("OK"); } }
公共类选项控制器:控制器 { 私有只读IWritableOptions\u writableLocations; 公共选项控制器(IWritableOptions可写位置) { _writableLocations=可写位置; } 公共IActionResult更改(字符串值) { _writableLocations.Update(opt=>{ opt.Name=值; }); 返回Ok(“Ok”); } }
- 它将触发
IOptionsMonitor.OnChange
IOptionsMonitor
,它只更改内存中的值,而不保存回appsettings.json
。为了解决这个问题,您需要实现自己的方法将更改保存回appsettings.json
- 定义从
IOptions继承的
IWritableOptions
public interface IWritableOptions<out T> : IOptions<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 IConfigurationRoot _configuration; private readonly string _section; private readonly string _file; public WritableOptions( IHostingEnvironment environment, IOptionsMonitor<T> options, IConfigurationRoot configuration, string section, string file) { _environment = environment; _options = options; _configuration = configuration; _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)); _configuration.Reload(); } }
- 配置
IWritableOptions
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 configuration = (IConfigurationRoot)provider.GetService<IConfiguration>(); var environment = provider.GetService<IHostingEnvironment>(); var options = provider.GetService<IOptionsMonitor<T>>(); return new WritableOptions<T>(environment, options, configuration, section.Key, file); }); } }
- 使用
public class OptionsController : Controller { private readonly IWritableOptions<Locations> _writableLocations; public OptionsController(IWritableOptions<Locations> writableLocations) { _writableLocations = writableLocations; } public IActionResult Change(string value) { _writableLocations.Update(opt => { opt.Name = value; }); return Ok("OK"); } }
公共类选项控制器:控制器 { 私有只读IWritableOptions\u writableLocations; 公共选项控制器(IWritableOptions可写位置) { _writableLocations=可写位置; } 公共IActionResult更改(字符串值) { _writableLocations.Update(opt=>{ opt.Name=值; }); 返回Ok(“Ok”); } }
- 它将触发
IOptionsMonitor.OnChange