准备
为了方便演示,我们先给出配置文件、文件提供程序的配置方式及配置对应的类的定义。
//settings.json { "key1": "value1", "key2": 0, "Section1": { "key3": "value3", "key4": 10, "key5": true } }
//文件提供程序 IConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); configurationBuilder.AddJsonFile("settings.json"); IConfigurationRoot configurationRoot = configurationBuilder.Build();
//ConfigModel class ConfigModel { public String key1 { get; set; } public int key2 { get; set; } public int key4 { get; set; } public bool key5 { get; private set; } = false; }
配置强类型绑定
配置加载完成后,我们可以根据需要定义响应的类,通过bind方法将配置绑定到类上,从而可以便捷的读取配置。类中属性的定义与配置中的键值相对应,而且,我们可以为不同的节定义不同的类,从而对配置进行更加清晰的管理。
Bind()方法
通过Bind方法,我们可以将配置绑定到配置类,为了区分,我们在如下的定义中对配置类做了初始值设置。
ConfigModel configModel = new ConfigModel() { key1 = "value1new", key2 = 10 ,key4=30}; configurationRoot.Bind(configModel);
此时运行,那么ConfigModel的key1、key2是有值的,但key4、key5无值,因此,我们还需要对包含key4、key5的节进行绑定。
configurationRoot.GetSection("Section1").Bind(configModel);
这样,我们就可以获取到key3和key4的值了,但是,key5依然无法访问,你知道为什么吗?因为key5是private的,我们没办法对其直接进行设置。
私有属性绑定
要将配置绑定到私有属性,要使用Bind方法的第二个参数BinderOptions,该参数有一个BindNonPublicProperties的属性,用于指示是否允许绑定到私有属性。
configurationRoot.GetSection("Section1").Bind(configModel,options=> { options.BindNonPublicProperties = true; });
这里,我们用options.BindNonPublicProperties = true来允许绑定到私有属性。这样,我们就可以获取key5的值了。
通过将不同的配置,甚至是同一配置下的不同节绑定到对应的配置类,我们可以很清晰的明确各配置间的关系并便捷的进行读取。
配置热更新
IChangeToken接口
通过配置强类型绑定,我们确实可以便捷的读取配置,但是,如果我们的配置发生了变化呢?是否会主动的重新加载?
配置框架中提供了IChangeToken接口,让我们可以来监听配置的变更,用法如下
IChangeToken changeToken = configurationRoot.GetReloadToken();
IChangeToken方法有一个RegisterChangeCallback的方法,通过该方法可以定义配置变更后的回调函数,如
changeToken.RegisterChangeCallback(state => { Console.WriteLine($"key1:{configurationRoot["key1"]}"); Console.WriteLine($"key2:{configurationRoot["key2"]}"); }, configurationRoot);
这样,我们在配置文件发生变化后,就会通过IChangeToken监听到该更改,并通过其回调方法来重新输出key1和key2的值。
但是,IChangeToken接口只能获取一次变更监听,也就是说,第二次更改就不会生效了,如果要继续,我们只能通过在其中继续定义该接口来实现。因此,微软为我们提供了另外的一个接口用来处理这种情形。
配置变更的持续监听
微软提供了一个ChangeToken的类,其中定义了OnChange的静态方法,该扩展方法有2个参数,一个是监听IChangeToken对象的委托,一个是其回调方法。
ChangeToken.OnChange(() => configurationRoot.GetReloadToken(), () => { Console.WriteLine($"key1:{configurationRoot["key1"]}"); Console.WriteLine($"key2:{configurationRoot["key2"]}"); });
通过该扩展方法即可实现配置变更的持续监听。
这里,我们的演示代码是以文件提供程序为例的,而且该种方式只适用于文件提供程序,内存配置、命令行配置、环境变量配置可以通过自定义的监听逻辑来实现,具体过程与上述类似,这里就不详说了,你可以自己试着写一下。
详细代码请参阅
https://github.com/IronMarmot/Samples/tree/master/CoreSamples