• 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>();
                });
    }

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

  • 相关阅读:
    delphi调用存储过程
    mysql存储过程中使用事务
    高性能JAVA开发之内存管理
    高效的找出两个List中的不同元素
    The reference to entity "characterEncoding" must end with the ';' delimiter
    Maven的安装、配置及使用入门
    如何在电脑上测试手机网站(全)
    三种常用的js数组去重方法
    oracle ORA-01461 错误 can bind a LONG value only for insert into a LONG column
    windows cmd下netstat查看占用端口号的进程和程序
  • 原文地址:https://www.cnblogs.com/jasonbourne3/p/14616665.html
Copyright © 2020-2023  润新知