加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-core – 如何将值更新到appsetting.json?

发布时间:2020-12-16 09:26:55 所属栏目:asp.Net 来源:网络整理
导读:我正在使用 in the official documentation所述的IOptions模式. 当我从appsetting.json读取值时,这工作正常,但是如何更新值并将更改保存回appsetting.json? 在我的例子中,我有几个字段可以从用户界面编辑(由管理员用户在应用程序中).因此,我正在寻找通过选
我正在使用 in the official documentation所述的IOptions模式.

当我从appsetting.json读取值时,这工作正常,但是如何更新值并将更改保存回appsetting.json?

在我的例子中,我有几个字段可以从用户界面编辑(由管理员用户在应用程序中).因此,我正在寻找通过选项访问器更新这些值的理想方法.

解决方法

在撰写此答案时,似乎没有Microsoft.Extensions.Options包提供的组件,该组件具有将配置值写回appsettings.json的功能.

在我的一个ASP.NET核心项目中,我想让用户更改一些应用程序设置 – 这些设置值应该存储在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",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,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 = "...";
});

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读