.NET Core 配置文件
老一代配置系统
1,XML格式 格式单一。
2,配置信息Kye,只能一维化配置
3,框架信息和应用程序信息混合到一起
应用程序中是 App.config
web项目中 web.config
使用程序集 System.Configuration
新一代配置系统
1支持配置文件格式 json xml init 环境变量 memory
2参数热加载
3参数多维
nuget包
Microsoft.Extensions.Configuration
主要是用上面的
下面的是对应不同文件类型的扩展 都是扩展方法
Microsoft.Extensions.Configuration.Json
Microsoft.Extensions.Configuration.Xml
Microsoft.Extensions.Configuration.Init
Microsoft.Extensions.Configuration.EnvironmentVariables
下面的是进行模型转换的
Microsoft.Extensions.Configuration.Binder
1、命令行读取
• 无前缀的key=value 模式
• 双中横线模式 --key=value 或 --key value
• 正斜杠模式 /key=value 或 /key value
• 备注: 等号分隔符和空格分隔符不能混
命令替换模式
• 必须以单划线(-) 或双划线(--) 开头
• 映射字典不能包含重复Ke
2、环境变量
分层:__对应: linux中不支持:
"SECTION1__SECTION2__KEY4": "value4",
configurationRoot.GetSection("SECTION1:SECTION2");
前缀过滤:
"KEY1": "value1",
"KEY2": "value2",
"XIAO_KEY1": "xiao key1"
//kye1有值 key2没有值 ,这里只会加载 XIAO_前缀的 builder.AddEnvironmentVariables("XIAO_"); var configurationRoot = builder.Build(); Console.WriteLine($"KEY1:{configurationRoot["KEY1"]}"); Console.WriteLine($"KEY2:{configurationRoot["KEY2"]}");
3、文件读取 json xml等
文件可选,文件变化 热加载,文件变化回调函数
var builder = new ConfigurationBuilder(); builder.AddJsonFile("appsettings.json");
var configurationRoot = builder.Build(); IChangeToken token = configurationRoot.GetReloadToken(); ChangeToken.OnChange(() => configurationRoot.GetReloadToken(), () => { Console.WriteLine($"Key1:{configurationRoot["Key1"]}"); Console.WriteLine($"Key2:{configurationRoot["Key2"]}"); Console.WriteLine($"Key3:{configurationRoot["Key3"]}"); });
4、自定义配置,这样就可以轻松的扩展配置框架,对不同的配置源读取
class MyConfigurationProvider : ConfigurationProvider { Timer timer; public MyConfigurationProvider() : base() { timer = new Timer(); timer.Elapsed += Timer_Elapsed; timer.Interval = 3000; timer.Start(); } private void Timer_Elapsed(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(); } } }
class MyConfigurationSource : IConfigurationSource { public IConfigurationProvider Build(IConfigurationBuilder builder) { return new MyConfigurationProvider(); } }
public static class MyConfigurationBuilderExtensions { public static IConfigurationBuilder AddMyConfiguration(this IConfigurationBuilder builder) { builder.Add(new MyConfigurationSource()); return builder; } }
把具体实现定义为私有的,以扩展的方式对外暴漏
数据读取
//1 : 运算符 层级管理 数据的话用索引 var dcf1 = config["mysql:host"]; Console.WriteLine(dcf1); var dcf11 = config["shopidlist:1:entid"]; Console.WriteLine(dcf11); //2 getsection getsection("")[""] var dcf2 = config.GetSection("mysql").GetSection("host").Value; Console.WriteLine(dcf2); var dcf21 = config.GetSection("mysql:host").Value; Console.WriteLine(dcf21); var dcf3 = config.GetSection("mysql")["host"]; Console.WriteLine(dcf3); var dcf4 = config.GetSection("shopidlist").GetSection("1")["entid"]; Console.WriteLine(dcf4); var dcf5 = config.GetSection("shopidlist").GetSection("1").GetSection("entid").Value; Console.WriteLine(dcf5); //3强类型读取 Microsoft.Extensions.Configuration.Binder //开发中常用强类型 var dcf6 = config.GetValue<int>("shopidlist:1:entid"); Console.WriteLine(dcf6); Rootobject dcf7 = new Rootobject(); config.Bind(dcf7); Console.WriteLine(dcf7.mysql.host);
弱类型方式读取
<1>: ':'运算符 mysql:host
IConfiguration configuration = new ConfigurationBuilder().SetBasePath(Environment.CurrentDirectory)
.AddJsonFile($"appsettings.json", optional: true, reloadOnChange: true)
//.AddXmlFile("appsettings.xml")
//.AddEnvironmentVariables()
.Build();
var info = configuration["shopidlist:0:entid"];
{
"mysql": {
"host": "192.168.23.1",
"port": 3306
},
"shopidlist": [
{ "entid": 20 },
{ "entid": 25 }
]
}
<2> GetSection (不同的人,不同的使用习惯) getSection("mysql")["host"]
//var info = configuration.GetSection("shopidlist").GetSection("1").GetSection("entid").Value;
var info = configuration.GetSection("shopidlist").GetSection("1")["entid"];
public IConfigurationSection GetSection(string key)
{
string[] textArray1 = new string[] { this.Path, key };
return this._root.GetSection(ConfigurationPath.Combine(textArray1));
}
强类型方式读取 : Microsoft.Extensions.Configuration.Binder
<1> GetValue
var info = configuration.GetValue<int>("mysql:port");
public static object GetValue(this IConfiguration configuration, Type type, string key, object defaultValue)
{
string str = configuration.GetSection(key).Value;
if (str != null)
{
return ConvertValue(type, str);
}
return defaultValue;
}
<2> 配置映射为实体类Bind,Get<T>
Rootobject rootobject = new Rootobject();
configuration.Bind(rootobject);
Configuration.GetSection("Position").Get<PositionOptions>();
StartUp类中 public void ConfigureServices(IServiceCollection services) { services.Configure<PositionOptions>(Configuration.GetSection("Position")); services.AddRazorPages(); } 其他类注入 public class Test2Model : PageModel { private readonly PositionOptions _options; public Test2Model(IOptions<PositionOptions> options) { _options = options.Value; } public ContentResult OnGet() { return Content($"Title: {_options.Title} \n" + $"Name: {_options.Name}"); } }
选项框架
• 接口分离原则 (ISP) ,我们的类不应该依赖它不使用的配置
只加载自己配置节点
• 关注点分离(SoC),不同组件、服务、类之间的配置不应相互依赖或耦
比如说服务里不应该依赖配置,而是依赖的IOptions<XXXOptions>。相当于ioption来解耦的
• 为我们的服务设计XXXOptions (RabbitMQOptions KafakaOptions ELKOptions。。。)
• 使用IOptions<XXXOptions> 、IOptionsSnapshot<XXXOptions> 、 IOptionsMonitor<XXXOptions> 作为服务构造函数的参数
options热更新
作用域配置服务类型使用IOptionsSnapshot<XXXOptions,单例配置服务使用IOptionsMonitor<XXXOptions> 。单例配置服务使用IOptionsSnapshot程序报错 。每次请求就会重新计算配置 值
注:IOptions<XXXOptions>不能感知配置变化
option监控变化
选项添加验证逻辑 三种方式 推荐第三种,这样就在配置错误的时候阻止应用启动
#region 添加验证 //1直接验证 //services.AddOptions<OrderServiceOptions>().Configure(options => //{ // configuration.Bind(options); //}).Validate(options => options.MaxOrderCount > 100); //2特性验证 //services.AddOptions<OrderServiceOptions>().Configure(options => //{ // configuration.Bind(options); //}).ValidateDataAnnotations(); //3自定义实现接口验证 services.AddOptions<OrderServiceOptions>().Configure(options => { configuration.Bind(options); }).Services.AddSingleton<IValidateOptions<OrderServiceOptions>>(new OrderServiceValidateOptions( )); #endregion
public class OrderServiceOptions { [Range(30, 100)] public int MaxOrderCount { get; set; } = 100; }