.net DI + option 强类型管理config

发布时间 2023-12-06 14:16:22作者: zhuweirandy

选项方式读取配置 推荐使用选项方式读取,和DI结合更好,且更好利用"reloadonchange”机制。

NuGet安装:Microsoft.Extensions.Options、Microsoft.Extensions.Configuration.Binder,当然也需要Microsoft.Extensions.Configuration、Microsoft.Extensions.Configuration.Json。

读取配置的时候,DI要声明IOptions、IOptionsMonitor、IOptionsSnapshot等类型。lOptions不会读取到新的值; 和IOptionsMonitor相比,IOptionsSnapshot会在同一个范围内(比如ASP.NET Core一个请求中) 保持一致。

建议IOptionsSnapshot。 在读取配置的地方,用IOptionsSnapshot注入 不要在构造函数里直接读取IOptionsSnapshot.Value, 是到用到的地方再读取,否则就无法更新变化。

代码

{
  "total": 1100,
  "num": 10,
  "teacher": {"address": "芜湖","name":"ssr","age": 18}
} 
public class Config
 {

     public int Total { get; set; }
     public int Num { get; set; }

     public Teacher? Teacher { get; set; }


 }
public class Teacher
{
    public int Age { get; set; }

    public string?  Address { get; set; }

    public string? Name { get; set; }
}
public class TestConfig
{
    /// <summary>
    /// 声明一个snapshot字段
    /// </summary>
    private readonly IOptionsSnapshot<Config> snapshot;
    /// <summary>
    /// 使用构造器方式进行注入值
    /// </summary>
    /// <param name="snapshot"></param>
    public TestConfig(IOptionsSnapshot<Config> snapshot)
    {
          this.snapshot = snapshot;
    }

    /// <summary>
    ///  读取值
    /// </summary>
    public void Test() 
    {
        var config= snapshot.Value;

        Console.WriteLine($"config.Num={config.Num},config.Teacher.Name={config.Teacher.Name}");  
    }
}
public class TestTeacher
{
    /// <summary>
    /// 声明一个snapshot字段
    /// </summary>
    private readonly IOptionsSnapshot<Teacher> snapshot;
    /// <summary>
    /// 使用构造器方式进行注入值
    /// </summary>
    /// <param name="snapshot"></param>
    public TestTeacher(IOptionsSnapshot<Teacher> snapshot)
    {
        this.snapshot = snapshot;
    }
    /// <summary>
    ///  读取值
    /// </summary>
    public void Test()
    {
        var teacher = snapshot.Value;

        Console.WriteLine($"teacher.Name={teacher.Name}");
    }
}
//创建ServiceCollection对象用来创建容器对象
ServiceCollection services = new ServiceCollection();

/*添加要管理的类*/
services.AddScoped<TestConfig>();
services.AddScoped<TestTeacher>();
//添加AddOptions,让DI来管理Options
var options= services.AddOptions();

/*读取配置*/
ConfigurationBuilder builder =new ConfigurationBuilder();
builder.AddJsonFile("config.json",optional:false,reloadOnChange:true);
IConfigurationRoot configRoot= builder.Build();

/*绑定类*/
//将json文件中的属性和config对象中的属性进行绑定
options.Configure<Config>(e => configRoot.Bind(e))
//将json文件中的teacher对象和teacher中的对象进行绑定
    .Configure<Teacher>(e=>configRoot.GetSection("teacher").Bind(e));


//创建容器对象
using (ServiceProvider provider= services.BuildServiceProvider())
{
    //从容器中获取TestConfig对象
    var testConfig = provider.GetRequiredService<TestConfig>();
    var testTeacher = provider.GetRequiredService<TestTeacher>();
    //调用方法
    testConfig.Test();
    testTeacher.Test();
}