ASP.NET Core框架学习之配置框架

配置是应用程序发布到各种环境的必备能力。.net core框架本身集成了强大的配置功能,支持多种配置源数据读写。

经常使用的nuget包

Microsoft.Extensions.Configuration.Abstractions   //抽象包
Microsoft.Extensions.Configuration           //实现包
Microsoft.Extensions.Configuration.Binder      //强类型绑定
Microsoft.Extensions.Configuration.Json        //配置Json文件 
Microsoft.Extensions.Primitives           //配置验证 
Microsoft.Extensions.Options //配置选项

框架核心接口

IConfigurationBuilder     //建造者接口
IConfigurationRoot        //配置根
IConfigurationSource    //配置源接口  
IConfigurationProvider  //配置提供程序接口

  配置框架应用了建造者模式,我们需要将配置源提交给建造者,通过建造者接口提供的build方法,创建IConfigurationRoot实例,它是配置的根,我们可以通过IConfigurationRoot实例访问到配置文件。通过实现IConfigurationSource ,IConfigurationProvider 两个接口,我们也可以在框架中添加自定义的配置源。

Web Api项目的简单实例

  在appsettings.json中设置配置文件

{
  "key1": "nihao",
  "section1": {
    "key1": [ "1", "2" ],
    "key2":4
  }
}

  构造函数中添加IConfiguration接口,并使用_configuration读取配置

private readonly IConfiguration _configuration; 
public WeatherForecastController(IConfiguration configuration)
{
      _configuration = configuration;
}

[HttpGet]
public string Get()
{
    Console.WriteLine(_configuration["key1"]);   //读取配置
    Console.WriteLine(_configuration.GetSection("section1")["key2"]);  
    return "OK";
}

  因为ASP.NET Core框架已经默认添加了appsettings.json的配置源,所以我们直接使用IConfiguration接口就可以读取到其中的配置,如果我们需要添加新的配置文件则需要手动添加(注意:后添加的配置源,会覆盖掉与前面配置源相同key的value值。)

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration(builder => {
            builder.AddJsonFile("dbsettings.json", false, true); //添加新的配置源  optional:是否可选,为false时,启动时未找到该配置文件会程序异常。 reloadOnChange:配置变更时,是否重新加载配置。
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
}

控制台程序实例

IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddJsonFile("appsettings.json", false, true);
var iconfigurationRoot = configurationBuilder.Build();
Console.WriteLine($"key1 {iconfigurationRoot["key1"]}");

强类型绑定

  配置框架支持将配置文件与类型绑定,它可以让我们使用配置更加方便,也使配置结构更加清晰。

  创建一个SectionOptions类型

public class SectionOptions
{
    public string[] key1 { get; set; }
    public int key2 { get; set; } = 2;
}

  在ConfigureServices方法中添加如下代码

var config = new SectionOptions()
{
};
Configuration.GetSection("section1").Bind(config, options =>  //将配置文件中的section1分段与config实例绑定
{
    options.BindNonPublicProperties = true; //支持私有属性绑定
});
services.AddSingleton<SectionOptions>(config);

  这样我们就可以在构造函数中引入SectionOptions,并通过它来读写配置文件了。

配置变更监听   

  给配置文件变更事件设置回调函数,当配置文件更新时,我们可以在回调函数中,做相应的逻辑处理

ChangeToken.OnChange(() =>
{
    return Configuration.GetReloadToken();
}, () =>
{
    Console.WriteLine(Configuration["key1"]);
});

配置选项

  配置选项模式让类型绑定变得更加简单、灵活。它支持三种模式:IOptions,IOptionsMonitor,IOptionsSnapshot。

  在ConfigureServices中添加如下代码

services.Configure<SectionOptions>(Configuration.GetSection("section1"));

  在构造函数中通过IOptions模式使用SectionOptions,它不能动态重载配置的变更

private readonly SectionOptions _sectionOptions; 
public WeatherForecastController(IOptions<SectionOptions> options)
{
    _sectionOptions = options.Value;
}

  在构造函数中通过IOptionsMonitor模式使用SectionOptions,它支持动态重载配置的变更,并保证每次读取的配置值都是最新的

private readonly SectionOptions _sectionOptions; 
public WeatherForecastController(IOptionsMonitor<SectionOptions> options)
{
    _sectionOptions = options.CurrentValue;
}

  在构造函数中通过IOptionsSnapshot模式使用SectionOptions,它支持动态重载配置的变更,但同一次请求域内,多次请求的值保持一致(可用来防止单次请求内由于配置文件变更引起的数据处理问题)

private readonly SectionOptions _sectionOptions; 
public WeatherForecastController(IOptionsSnapshot<SectionOptions> options)
{
    _sectionOptions = options.Value;
}

配置验证

  配置框架还提供了三种配置验证的机制,当配置错误时,使用该配置程序会抛出异常。

  DataAnnotations特性验证,在模型中使用DataAnnotations特性标记  

services.AddOptions<SectionOptions>().Configure(option => {
            Configuration.GetSection("section1").Bind(option);
        }).ValidateDataAnnotations();

  函数验证,在绑定配置时,直接注入验证函数

 services.AddOptions<SectionOptions>().Configure(option => {
            Configuration.GetSection("section1").Bind(option);
        }).Validate(section =>
        {
            return section.key2 > 1;
        });

  实现IValidateOptions接口

public class SectionValidateOptions : IValidateOptions<SectionOptions>
{
    public ValidateOptionsResult Validate(string name, SectionOptions options)
    {
        if (options.key2 > 100)
        {
            return ValidateOptionsResult.Fail("key2 不能大于100");
        }
        else
        {
            return ValidateOptionsResult.Success;
        }    
    }
}
//在ConfigureServices方法中添加如下代码
 services.AddOptions<SectionOptions>().Configure(option => {          
       Configuration.GetSection("section1").Bind(option);
    }).Services.AddSingleton<IValidateOptions<SectionOptions>, SectionValidateOptions>();

 后配置处理

  配置框架还提供了方法让我们对配置数据进行处理

services.PostConfigure<SectionOptions>(options =>
{
       options.key2 += 10;
});

自定义配置源

   通过实现下面的两个接口,我们可以实现自己的配置提供程序,它可以用来获取远程配置中心的配置。

public class MyConfigurationSource : IConfigurationSource
{
    public IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        return new MyConfigurationProvider();
    }
}

public class MyConfigurationProvider :  ConfigurationProvider, IConfigurationProvider
{
    public MyConfigurationProvider()
    {
        var timer = new Timer();
        timer.Elapsed += Timer_Elapsed;
        timer.Interval = 3000;
        timer.Start();
    }

    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        Load(true);
    }

    public void Load()
    {
        Load(false);
    }

    private void Load(bool reload = false)
    {
        //可以在这里加载远程配置中心的配置
        this.Data["lastdatetime"] = $"{DateTime.Now}";
        if (reload)
        {
            base.OnReload();
        }
    }
}

  添加自定义配置源

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration(builder => {
        //    builder.Add(new MyConfigurationSource());  //添加自定义配置源
        })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

  这样我们就可以通过配置框架获取到自定义配置源中的数据了。

posted @ 2021-04-04 18:10  唐磊(Jason)  阅读(244)  评论(0编辑  收藏  举报