配置系统学习_2 选项方式读取配置文件

文章讲述了如何在.NET应用中使用Microsoft.Extensions.Options库,特别是IOptionsSnapshot,以实现配置文件的动态刷新。通过实例演示了如何在控制器中注入IOptionsSnapshot并展示其在配置更新时自动获取新值的能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

用法

  1. 推荐使用选项方式读取,和DI结合更好,而且更好利用"raloadonchange"机制。
  2. NuGet安装:
    Microsoft.Extensions.Options & Microsoft.Extensions.Configuration.Binder & Microsoft.Extensions.Configuration & Microsoft.Extensions.Configuration.Json
  3. 读取配置的时候,DI要声明IOptions<T> 、 IOptionsMonitor<T>、IOptionsSnapshot<T>等类型。 IOptions<T>不会读取到新的值;和IOptionsMonitor<T>相比,IOptionsSnapshot<T>会在同一个范围内保持一致。建议使用IOptionsSnapshot。

2 演示代码

TestController类

using System;
using Microsoft.Extensions.Options;

namespace 配置系统学习_2
{
    class TestController
    {
        // di注入的对象一般都写成readonly的
        private readonly IOptionsSnapshot<Config> optionsSnapshot;
        // private readonly Config config;

        public TestController(IOptionsSnapshot<Config> optionsSnapshot)
        {
            //不要写成下面这种形式,这样写是在注入时就取到配置文件中的值
            //但是以后更改配置文件的话会取不到更新的值
            //this.config = optionsSnapshot.Value;

            // 要拿到optionsSnapshot,它会在配置文件作修改时帮我们取到新的值
            this.optionsSnapshot = optionsSnapshot;
        }

        public void Test()
        {
            Console.WriteLine(optionsSnapshot.Value.Age);
            Console.WriteLine("********");
            Console.WriteLine(optionsSnapshot.Value.Age);
        }
    }
}

Program类

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace 配置系统学习_2;
class Program
{
    static void Main(string[] args)
    {
        ServiceCollection services = new ServiceCollection();
        services.AddScoped<TestController>();

        ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
        configurationBuilder.AddJsonFile("Config.json", optional: true, reloadOnChange: true);
        IConfigurationRoot configRoot = configurationBuilder.Build();

        services.AddOptions().Configure<Config>(e => configRoot.Bind(e));

        using (ServiceProvider sp = services.BuildServiceProvider())
        {
            TestController controller = sp.GetRequiredService<TestController>();
            controller.Test();
        }
    }
}

class Proxy
{
    public string Address { get; set; }

    public int Port { get; set; }
}

class Config
{
    public string Name { get; set; }

    public int Age { get; set; }

    public Proxy Proxy { get; set; }
}

congfig.json 配置文件

{
    "name": "mzz",
    "age": 58,
    "proxy": {
        "address": "ttt",
        "port": 1844
    }
}

在这里插入图片描述
如果我们只想读proxy的配置内容,不想将整个config读出来,怎么办?

新增一个TestController2

using System;
using Microsoft.Extensions.Options;

namespace 配置系统学习_2
{
    class TestController2
    {
        private readonly IOptionsSnapshot<Proxy> optionSnapshot;

        public TestController2(IOptionsSnapshot<Proxy> optionSnapshot)
        {
            this.optionSnapshot = optionSnapshot;
        }

        public void Test2()
        {
            Console.WriteLine(this.optionSnapshot.Value.Address);
        }
    }
}

Program 类

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace 配置系统学习_2;
class Program
{
    static void Main(string[] args)
    {
        ServiceCollection services = new ServiceCollection();
        services.AddScoped<TestController2>();

        ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
        configurationBuilder.AddJsonFile("Config.json", optional: true, reloadOnChange: true);
        IConfigurationRoot configRoot = configurationBuilder.Build();

        // 这句最重要 是将配置文件的对应类绑定到root上,可以绑定多个配置配件
        services.AddOptions()
            .Configure<Proxy>(e => configRoot.GetSection("proxy").Bind(e));

        using (ServiceProvider sp = services.BuildServiceProvider())
        {
            var controller2 = sp.GetRequiredService<TestController2>();
            controller2.Test2();
        }
    }
}

class Proxy
{
    public string Address { get; set; }

    public int Port { get; set; }
}

class Config
{
    public string Name { get; set; }

    public int Age { get; set; }

    public Proxy Proxy { get; set; }
}

到这里,我们还没有看出来snapshot在一定范围内加载同一个值是什么意思,我们现在将program类中的代码改变一下:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace 配置系统学习_2;
class Program
{
    static void Main(string[] args)
    {
        ServiceCollection services = new ServiceCollection();
        services.AddScoped<TestController>();

        ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
        configurationBuilder.AddJsonFile("Config.json", optional: true, reloadOnChange: true);
        IConfigurationRoot configRoot = configurationBuilder.Build();

        // 这句最重要 是将配置文件的对应类绑定到root上,可以绑定多个配置配件
        services.AddOptions()
            .Configure<Config>(e => configRoot.Bind(e));

        using (ServiceProvider sp = services.BuildServiceProvider())
        {
            while (true)
            {
                using (IServiceScope scope = sp.CreateScope())
                {
                    var controller = scope.ServiceProvider.GetRequiredService<TestController>();
                    controller.Test(); // 配置文件中age=58 

                    Console.WriteLine("please change the age:");//改为38
                    Console.ReadKey();
                    controller.Test();
                }

                Console.WriteLine("please press any key to continue");
                Console.ReadKey();
            }
        }
    }
}

class Proxy
{
    public string Address { get; set; }

    public int Port { get; set; }
}

class Config
{
    public string Name { get; set; }

    public int Age { get; set; }

    public Proxy Proxy { get; set; }
}

在这里插入图片描述
最能体现snapshot在一定范围内加载同一个值的是下面这段代码。我们写一个循环,在这个循环里面创建了一个scope,在这个scope里面分别打印了两次config中的age,一次在修改age前,一次在修改age后,由运行结果可知,这两次的结果是一致的。之后进入下一个循环打印出来的是修改过后的age值。
这里有个点需要注意:修改config文件时,修改的不是和项目同级的json文件,而是和exe同一个目录下面的json文件。具体可参照上篇文章。

            while (true)
            {
                using (IServiceScope scope = sp.CreateScope())
                {
                    var controller = scope.ServiceProvider.GetRequiredService<TestController>();
                    controller.Test(); // 配置文件中age=58 

                    Console.WriteLine("please change the age:");//改为38
                    Console.ReadKey();
                    controller.Test();
                }

                Console.WriteLine("please press any key to continue");
                Console.ReadKey();
            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值