【NetCore】06-配置框架

1.配置框架

1.1 核心包

  • Microsoft.Extensions.Configuration.Abstractions
  • Microsoft.Extensions.Configuration

以Key-value键值对方式抽象配置,支持从不同数据源读取配置,如环境变量,数据库等

1.2 配置框架核心类型

  • IConfiguration
  • IConfigurationRoot
  • IConfigurationSection
  • IConfigurationBuilder

1.3 配置框架扩展点

  • IConfigurationSource
  • IConfigurationProvider
static void Main(string[] args)
{
	IConfigurationBuilder builder = new ConfigurationBuilder();
	
	builder.AddInMemoryCollection(new Dictionary<string,string>()// 注入内存的配置数据源
	{
		{"key1","value1"},
		{"key2","value2"},
		{"section1:key4","value4"} ,// section用于配置分组
		{"section2:key5","value5"} ,
		{"section2:key6","value6"} ,
		{"section2:section3:key7","value7"} ,// 多层嵌套
	});
	
	IConfigurationRoot configurationRoot = builder.Build();// 构建所有配置

	Console.WriteLine(configurationRoot["key1"]);// 读取配置
	Console.WriteLine(configurationRoot["key2"]);
	
	// 获取section
   IConfigurationSection section = configurationRoot.GetSection("sction1");
   Console.Writeline(section["key4"]); // 输出结果为 value4
   Console.WriteLine(section["key5"]); // 无法获取值
   
    IConfigurationSection section2 = configurationRoot.GetSection("sction2");
    Console.WriteLine(section["key5"]); // 输出结果为value5
    
    var section3 = section2.GetSection("section3");// 多层嵌套的读取
    Console.WriteLine(section3["key7"]);// 输出结果为value7
}


2.命令行配置提供程序

2.1 支持的命令格式

  • 无前缀的key=value 模式
  • 双中横线模式 --key=value 或 – key value
  • 正斜杠模式 /key=value 或 /key value

备注 : 等号分隔符和空格分隔符不能混用

2.2 命令替换模式

就是可以给命令取别名

  • 必须以单划线(-)或双划线(–)开头
  • 映射字典不能包含重复key
// 控制台应用程序
static void Main(string[] args)
{
	var builder = new ConfigurationBuilder();
	builder.AddCommandLine(args);
	
	// 命令替换
	//var mapper = new Dictionary<string,string>{{"-k1","CommandLineKey1"}};// 把-k1的值换给CommandLineKey1
	//builder.AddCommandLine(args,mapper);

	var configurationRoot = builder.Builder();
	Console.WriteLine($"CommandLineKey1:{configurationRoot["CommandLineKey1"]}");
	Console.ReadKey();
}

在项目属性-调试-应用程序参数中设置启动参数 ,设置四个参数

CommandLineKey1=value1 --CommandLineKey2=value2 /CommandLineKey3=value3 -k1=k3

3. 环境变量配置提供程序

3.1 使用场景

  • 在Docker中运行时
  • 在Kubernetes中运行时
  • 需要配置Asp.NetCore的一些内置特殊配置时

3.2 特性

  • 对于配置的分层键,支持用双下横线"__“代替”:"
  • 支持根据前缀加载
static void Main(string[] args)
{
	var builder = new ConfigurationBuilder();
	builder.AddEnvironmentVariables();
	
	var configurationRoot = builder.Builder();
	Console.WriteLine($"key1:{configurationRoot["CommandLineKey1"]}");
	
	// 分层键
	var section = configurationRoot.GetSection("SECTION1");
	Console.WriteLine($"KEY3:{section["KEY3"]}"); // 输出为 : value3

   // 前缀过滤
   builder.AddEnvironmentVariables("XIAO_");
   var configurationRoot = builder.Builder();
   Console.WriteLine($"key1:{configurationRoot["KEY1"]}");
   
}

环境变量配置:
项目右键-属性-调试,设置环境变量
在这里插入图片描述

4.文件配置提供程序

4.1 文件配置提供程序

  • Micosoft.Extensions.Configuration.Ini
  • Micosoft.Extensions.Configuration.Json
  • Microsoft.Extensions.Configuration.NewtonsoftJson
  • Microsoft.Extensions.Configuration.Xml
  • Microsoft.Extensions.Configuration.UserSecrets

4.2 特性

  • 指定文件可选、必选
  • 指定是否监视文件的变更
// 控制台程序
static void Main(string[] args)
{ 
	var builder = new ConfigurationBuilder();
	// optional表示文件是否可选,默认为false,表示文件不存在时会报错
	// reloadChange表示文件变更是否重新读取,默认为true
	builder.AddJsonFile("appsettings.json",optional:false,reloadOnChange:true);
	builder.AddIniFile("appsetting.ini");// 这个配置会覆盖前面的配置信息,优先级更高
	var configurationRoot = builder.Builder();

	Console.WriteLine($"Key1:{configurationRoot["Key1"]}");// 输出结果 value1
	Console.WriteLine($"Key2:{configurationRoot["Key2"]}");// 输出结果value2
	Console.WriteLine($"Key3:{configurationRoot["Key3"]}");// 输出为空
	Console.ReadKey();
}

引用程序包
在这里插入图片描述

appsettings.json配置
在这里插入图片描述

5.配置变更监听-配置热更新能力的核心

5.1 场景

  • 需要记录配置源的变更时
  • 需要在配置数据变更时触发特定操作时

5.2 关键方法

  • IChangeTokenIconfiguration.GetReloadToken()
// 控制台程序
static void Main(string[] args)
{ 
	var builder = new ConfigurationBuilder();
	builder.AddJsonFile("appsettings.json",optional:true,reloadOnChange:true);
	var configurationRoot = builder.Builder();

	IChangeToken token =  configurationRoot.GetReloadToken();//IChangeToken只能使用一次

	ChangeToken
	
	token.RegisterChageCallback(state => { // 修改配置文件时读取
		Console.WriteLine($"Key1:{configurationRoot["Key1"]}");
		Console.WriteLine($"Key2:{configurationRoot["Key2"]}");
		Console.WriteLine($"Key3:{configurationRoot["Key3"]}");
	},configurationRoot);
	Console.ReadKey();
	
	//Console.WriteLine($"Key1:{configurationRoot["Key1"]}");
	//Console.WriteLine($"Key2:{configurationRoot["Key2"]}");
	//Console.WriteLine($"Key3:{configurationRoot["Key3"]}");
	//Console.ReadKey();
}

appsettings.json配置
在这里插入图片描述
注意:这里只能监听到一次配置文件的修改,修改一次后再次修改,将无法捕获到修改信息
因为IChangeToken对象只能使用一次,如果需要持续监听,需要在结束后重新获取一次IChangeToken,如下代码所示

// 改进后代码
// 控制台程序
static void Main(string[] args)
{ 
	var builder = new ConfigurationBuilder();
	builder.AddJsonFile("appsettings.json",optional:true,reloadOnChange:true);
	var configurationRoot = builder.Builder();

	IChangeToken token =  configurationRoot.GetReloadToken();//IChangeToken只能使用一次
	// 持续监听修改
	ChangeToken.OnChange(() => configurationRoot.GetReloadToken(),()=>
	{
		Console.WriteLine($"Key1:{configurationRoot["Key1"]}");
		Console.WriteLine($"Key2:{configurationRoot["Key2"]}");
		Console.WriteLine($"Key3:{configurationRoot["Key3"]}");
	});
	Console.ReadKey();
}


6.配置绑定-使用强类型对象承载配置数据

6.1 要点

  • 支持将配置值绑定到已有对象
  • 支持将配置值绑定到私有属性上(默认情况只能绑定public属性)

// 控制台程序
static void Main(string[] args)
{ 
	var builder = new ConfigurationBuilder();
	builder.AddJsonFile("appsettings.json",optional:true,reloadOnChange:true);
	var configurationRoot = builder.Builder();
	
	var config = new Config();
	config.Key1 = "config key1";
	config.Key5 = true;
	config.Key6 = 100;
	
	configurationRoot.Bind(config);
	//configurationRoot.GetSection("section名称").Bind(config);//多层级绑定
	Console.WriteLine($"Key1:{config.Key1}");// 输出Key1:Value1
	Console.WriteLine($"Key5:{config.Key5}");// 输出Key5:false
	Console.WriteLine($"Key6:{config.Key6}");// 输出Key6:10
}


class Config
{
	public string Key1 { get; set;}
	public bool Key5 { get; set;}
	public int Key6 { get; set;}
}


appsettings.json配置
在这里插入图片描述

通常会遇到多层级的配置,采用如下方式

static void Main(string[] args)
{ 
	var builder = new ConfigurationBuilder();
	builder.AddJsonFile("appsettings.json",optional:true,reloadOnChange:true);
	var configurationRoot = builder.Builder();
	
	var config = new Config();
	config.Key1 = "config key1";
	config.Key5 = true;
	config.Key6 = 100;
	
	configurationRoot.GetSection("OrderService").Bind(config,binderOptions => {
				binderOptions.BindNonPublicProperties = true; //BindNonPublicProperties 私有属性是否绑定.默认false
			});//多层级绑定
	Console.WriteLine($"Key1:{config.Key1}");// 输出Key1:order key1
	Console.WriteLine($"Key5:{config.Key5}");// 输出Key5:true
	Console.WriteLine($"Key6:{config.Key6}");// 输出Key6:200
	// 读取到的是appsettings.json中内容
}

对应的appsettings.json如下
在这里插入图片描述

一般推荐使用强类型进行绑定,Bind方法在开发中使用会比较多

7.自定义配置数据源-低成本实现定制化配置方法

7.1 扩展步骤

  • 实现IConfigurationSource
  • 实现IConfigurationProvider
  • 实现Addxxx扩展方法

IConfigurationSource

	class MyConfigurationSource : IConfigurationSouce
	{
		public IConfigurationProvider Builde(IConfigurationBuilder builder)
		{
			return new MyConfigurationProvider();
		}
	}

	using System.Timers.Timer;
	public class MyConfigurationProvider : ConfigurationProvider
    {
        Timer timer;

        public MyConfigurationProvider() : base()
        {
            timer = new Timer();
            timer.Elapsed += Timer_Elasped;
            timer.Interval = 3000;
            timer.Start();
        }

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

        public override void Load()
        {
            // 加载数据
            Load(false);
        }

        void Load(bool reload)
        {
            this.Data["lastTime"] = DateTime.Now.ToString();
            if (reload)
            {
                base.OnReload();
            }
        }
    }

	// 定义扩展方法,暴露在外的扩展方法,不需要将具体的配置源实现向外暴露
	namespace Microsoft.Extensions.Configuration // 使用Configuration命名空间
	{
	    public static class MyConfigurationBuilderExtensions
	    {
	        public static IConfigurationBuilder AddMyConfiguration(this IConfigurationBuilder builder)
	        {
	            builder.Add(new MyConfigurationSource());
	            return builder;
	        }
	    }
	}

	static void Main(string[] args)
	{
		var builder = new ConfigurationBuilder();
		//builder.Add(new MyConfigurationSource());// 直接读取具体配置
		builder.AddMyConfiguration();/ 通过扩展方法获取
		
		var configRoot = builder.Build();
		// 持续监听
		ChangeToken.OnChange(() => configRoot.GetReloadToken(), () =>
		{
		    var value = configRoot["lastTime"];
		    Console.WriteLine(value);
		});

		Console.WriteLine("开始了");
		Console.ReadKey();
	}

定义扩展时,将具体的实现定义为私有的internal,然后通过扩展方法的方式暴露出去
输出结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值