在ASP.NET Core 2.1中,我使用IOptionsMonitor <>并进行了设置,以便在更改appSettings.json文件时可以成功获取事件。这样就可以了。
我现在要做的是通过代码手动更改选项中的某些值,并触发所有监视器。这可能吗?
答案 0 :(得分:2)
对于IOptionsMonitor<Locations>
,它只会更改内存中的值,而不会保存回appsettings.json
。要解决此问题,您将需要实现自己的方法来将更改保存回appsettings.json
。
定义从IWritableOptions
继承的IOptions
public interface IWritableOptions<out T> : IOptions<T> where T : class, new()
{
void Update(Action<T> applyChanges);
}
实现自己的WritableOptions
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<T>
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);
});
}
}
在Startup
中注册
services.ConfigureWritable<Locations>(Configuration.GetSection("Locations"));
使用
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");
}
}
它将触发IOptionsMonitor<>.OnChange