第十节:Asp.Net Core 配置详解和选项模式
一. 各种文件的读取
1.说明
在.Net Core中,各种配置文件的读取都需要依赖【Microsoft.Extensions.Configuration】程序集,当然在Asp.Net Core中已经内置了,然后通过依赖注入IConfiguration configuration对象进行配置文件的相关操作。
比如在控制器注入该对象:
相关约定:
①:配置键不区分大小写,例如,ConnectionString 和 connectionstring 被视为等效键。
②:在配置API中,冒号分隔符(:)适用于所有平台。
③:配置值是字符串
④:NULL值不能存储在配置中或绑定到对象。
注:
在Core MVC中,默认识别appsettings.json 文件,如果要添加其它类型的文件,需要通过AddJson、AddXml、AddIniFile、AddInMemoryCollection等方法手动添加进入, 方便起见通过 config.SetBasePath(Directory.GetCurrentDirectory());将当前目录设置为基础目录。
这些AddXX方法,可以配置后面两个参数均为true,eg:config.AddJsonFile("Config/ypf1.json", optional: true, reloadOnChange: true);这样的话当配置文件发生变化的时候,会自动更新加载,而不必重启整个项目。
项目结构:手动新增的配置文件都在Config文件夹下(如下图),然后都在Program类中进行加载进来(代码如下)
1 public class Program 2 { 3 public static readonly Dictionary<string, string> _dict = new Dictionary<string, string> 4 { 5 {"MKey1", "value1"}, 6 {"MKey2", "value2"} 7 }; 8 9 public static void Main(string[] args) 10 { 11 CreateWebHostBuilder(args).Build().Run(); 12 } 13 14 public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 15 WebHost.CreateDefaultBuilder(args) 16 //配置相关 17 .ConfigureAppConfiguration((hostingContext, config) => 18 { 19 //1. 设置当前目录为基础目录(后面则可以用相对路径) 20 config.SetBasePath(Directory.GetCurrentDirectory()); 21 //2. 加载json文件 (配置后面两个参数为true,当配置文件发生变化的时候,会自动更新加载,而不必重启整个项目) 22 config.AddJsonFile("Config/ypf1.json", optional: true, reloadOnChange: true); 23 //3. 加载xml文件 24 config.AddXmlFile("Config/ypf2.xml"); 25 config.AddXmlFile("Config/ypf3.xml"); 26 //4. 加载ini文件 27 config.AddIniFile("Config/ypf4.ini"); 28 //5. 加载内存文件 29 config.AddInMemoryCollection(_dict); 30 }) 31 .UseStartup<Startup>(); 32 }
2. Json文件的读取
(1).读取规则:
A:普通对象直接通过键名来读取; B:对象中套对象通过多个键名(中间通过:连接)来读取;C: 数组对象则可以 键名:0(或1 或2)的方式来读取。
(2).实战演练:
① 项目默认的appsettings.json的读取,
1 { 2 "Logging": { 3 "LogLevel": { 4 "Default": "Warning" 5 } 6 }, 7 "AllowedHosts": "*", 8 //下面自定义一些值,用于测试配置文件的读取 9 "MyFullName": "Maru Li", 10 "User": { 11 "userName": "ypf", 12 "userAge": 15, 13 "Child": { 14 "childName": "ydb", 15 "age": 12 16 } 17 }, 18 "StudentList": [ 19 { 20 "sName": "qdkjdx" 21 }, 22 { 23 "sName": "bjdx" 24 } 25 ], 26 //测试绑定类 27 "starship": { 28 "name": "USS Enterprise", 29 "registry": "NCC-1701", 30 "class": "Constitution", 31 "length": 304.8, 32 "commissioned": false 33 }, 34 //测试绑定数组 35 "myArray": ["001","002","003"], 36 "json_array": { 37 "key": "valueA", 38 "subsection": [ 39 "valueB", 40 "valueC", 41 "valueD" 42 ] 43 } 44 45 46 47 }
1 { 2 var f0 = Configuration["MyFullName"]; 3 var f1 = Configuration["User:userName"]; 4 var f2 = Configuration["User:Child:childName"]; 5 var f3 = Configuration["StudentList:0:sName"]; 6 var f4 = Configuration["StudentList:1:sName"]; 7 }
注:这里有一种特殊情况,比如数据库连接字符,通常是放在ConnectionStrings节点下的某个节点,所以可以通过 Configuration.GetConnectionString("xxx");来读取, 等价于:Configuration["ConnectionStrings:xxx"];
1 { 2 "ConnectionStrings": { 3 "conn1": "sqlServer", 4 "conn2": "mySql" 5 } 6 }
1 { 2 //数据库连接字符串读取 3 var c1 = Configuration["ConnectionStrings:conn1"]; 4 var c2 = Configuration["ConnectionStrings:conn2"]; 5 //等价于上面的 6 var c3 = Configuration.GetConnectionString("conn1"); 7 var c4 = Configuration.GetConnectionString("conn2"); 8 }
② 在Config文件夹中新增ypf1.json的读取:需要在Program类中通过代码 config.AddJsonFile("Config/ypf1.json"); 加载进来该json文件
1 { 2 "FullName": "ypf" 3 }
1 { 2 var f0 = Configuration["FullName"]; 3 }
3. xml文件的读取
① 不存在重复节点,如:ypf2.xml 两个节点分别为section0 和 section1,可以明显的区分。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <configuration> 3 <section0> 4 <key0>value001</key0> 5 <key1>value002</key1> 6 </section0> 7 <section1> 8 <key0>value003</key0> 9 <key1>value004</key1> 10 </section1> 11 </configuration>
1 { 2 var f0 = Configuration["section0:key0"]; 3 var f1 = Configuration["section0:key1"]; 4 var f2 = Configuration["section1:key0"]; 5 var f3 = Configuration["section1:key1"]; 6 }
② 存在重复节点,如:ypf3.xml,两个相同section节点,则需要通过name属性来区分,section下两个相同的key节点,也需要通过name来区分
1 <?xml version="1.0" encoding="UTF-8"?> 2 <configuration> 3 <section name="section0"> 4 <key name="key0">value101</key> 5 <key name="key1">value102</key> 6 </section> 7 <section name="section1"> 8 <key name="key0">value103</key> 9 <key name="key1">value104</key> 10 </section> 11 </configuration>
1 { 2 var f0 = Configuration["section:section0:key:key0"]; 3 var f1 = Configuration["section:section0:key:key1"]; 4 var f2 = Configuration["section:section1:key:key0"]; 5 var f3 = Configuration["section:section1:key:key1"]; 6 }
4. INI 配置文件的读取
结合[]类似特性的标记进行读取,如ypf4.ini。
1 [section0] 2 key0=value201 3 key1=value202 4 5 [section1] 6 subsection:key=value203 7 8 [section2:subsection0] 9 key=value204 10 11 [section2:subsection1] 12 key=value205
1 { 2 var f0 = Configuration["section0:key0"]; 3 var f1 = Configuration["section0:key1"]; 4 var f2 = Configuration["section1:subsection:key"]; 5 var f3 = Configuration["section2:subsection0:key"]; 6 var f4 = Configuration["section2:subsection1:key"]; 7 }
5. 内存集合的读取
通过AddInMemoryCollection添加内存集合,如_dic。
1 { 2 var f0 = Configuration["MKey1"]; 3 var f1 = Configuration["MKey2"]; 4 }
另外:还有环境变量、命令行的读取均不常用,这里不详细介绍了。
6. 单独封装帮助类
首先要下载一系列程序集,如下图:
注:如果在控制台使用的话,需要将被读取的文件属性改为"始终复制"。
分享封装代码:
1 /// <summary> 2 /// 读取配置文件 3 /// </summary> 4 public static class ConfigHelp 5 { 6 /// <summary> 7 /// 读取Json类型的配置文件 8 /// </summary> 9 /// <param name="key">键名</param> 10 /// <param name="FilePath">文件路径,默认为:appsettings.json</param> 11 /// <returns></returns> 12 public static string GetString(string key, string FilePath = "appsettings.json") 13 { 14 var configurationBuilder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile(FilePath, optional: true, reloadOnChange: true); 15 var configuration = configurationBuilder.Build(); 16 return configuration[key]; 17 } 18 /// <summary> 19 /// 读取Xml类型的配置文件 20 /// </summary> 21 /// <param name="key">键名</param> 22 /// <param name="FilePath">文件路径,默认为:myXml.json</param> 23 /// <returns></returns> 24 public static string GetXmlString(string key, string FilePath = "myXml.json") 25 { 26 var configurationBuilder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddXmlFile(FilePath, optional: true, reloadOnChange: true); 27 var configuration = configurationBuilder.Build(); 28 return configuration[key]; 29 } 30 31 }
二. 方法和绑定
1. 常用方法
① GetValue<T>:从具有指定键的配置中提取一个值,并将其转换为指定类型。 如果未找到该键,则过载允许你提供默认值。
② GetSection:使用指定的子节键提取配置子节,永远不会返回 null。 如果找不到匹配的节,则返回空 IConfigurationSection。如果有值,则在后面通过.Value来获取。
③ GetChildren:获得 IEnumerable<IConfigurationSection>
④ Exits:判断配置节是否存在
代码分享:
1 { 2 "Logging": { 3 "LogLevel": { 4 "Default": "Warning" 5 } 6 }, 7 "AllowedHosts": "*", 8 //下面自定义一些值,用于测试配置文件的读取 9 "MyFullName": "Maru Li", 10 "User": { 11 "userName": "ypf", 12 "userAge": 15, 13 "Child": { 14 "childName": "ydb", 15 "age": 12 16 } 17 }, 18 "StudentList": [ 19 { 20 "sName": "qdkjdx" 21 }, 22 { 23 "sName": "bjdx" 24 } 25 ], 26 //测试绑定类 27 "starship": { 28 "name": "USS Enterprise", 29 "registry": "NCC-1701", 30 "class": "Constitution", 31 "length": 304.8, 32 "commissioned": false 33 }, 34 //测试绑定数组 35 "myArray": ["001","002","003"], 36 "json_array": { 37 "key": "valueA", 38 "subsection": [ 39 "valueB", 40 "valueC", 41 "valueD" 42 ] 43 } 44 45 }
1 { 2 //这里使用默认的appsettings.json来进行测试 3 //1. GetValue 4 var f0 = Configuration.GetValue<string>("MyFullName"); 5 //如果没有该键,则赋值noValue 6 var f1 = Configuration.GetValue<string>("MyFullName111", "noValue"); 7 var f2 = Configuration.GetValue<string>("User:userName"); 8 //2. GetSection 9 var section0 = Configuration.GetSection("User"); 10 var section1 = Configuration.GetSection("User1"); 11 var section2 = Configuration.GetSection("User:userName"); 12 var section2Value = section2.Value; 13 //3. GetChildren 14 var child0 = section0.GetChildren(); 15 //4. Exist 16 var isExist0 = Configuration.GetSection("User:userName").Exists(); 17 var isExist1 = Configuration.GetSection("User:userName1").Exists(); 18 }
2. 绑定
借助Bind方法,可以直接读取配置文件中的内容然后赋值给类或对象,如果配置文件是xml文件,不再需要像传统的.Net 那样,解析或者序列化了,可以直接赋值。
这里还是用上面的appsetting.json这个文件进行测试。
再次重复appsetting.json代码
1 { 2 "Logging": { 3 "LogLevel": { 4 "Default": "Warning" 5 } 6 }, 7 "AllowedHosts": "*", 8 //下面自定义一些值,用于测试配置文件的读取 9 "MyFullName": "Maru Li", 10 "User": { 11 "userName": "ypf", 12 "userAge": 15, 13 "Child": { 14 "childName": "ydb", 15 "age": 12 16 } 17 }, 18 "StudentList": [ 19 { 20 "sName": "qdkjdx" 21 }, 22 { 23 "sName": "bjdx" 24 } 25 ], 26 //测试绑定类 27 "starship": { 28 "name": "USS Enterprise", 29 "registry": "NCC-1701", 30 "class": "Constitution", 31 "length": 304.8, 32 "commissioned": false 33 }, 34 //测试绑定数组 35 "myArray": ["001","002","003"], 36 "json_array": { 37 "key": "valueA", 38 "subsection": [ 39 "valueB", 40 "valueC", 41 "valueD" 42 ] 43 } 44 45 46 47 }
类代码:
1 public class Starship 2 { 3 public string Name { get; set; } 4 public string Registry { get; set; } 5 public string Class { get; set; } 6 public decimal Length { get; set; } 7 public bool Commissioned { get; set; } 8 } 9 public class User 10 { 11 public string userName { get; set; } 12 public int userAge { get; set; } 13 public Child child { get; set; } 14 } 15 16 public class Child 17 { 18 public string childName { get; set; } 19 public int age { get; set; } 20 } 21 public class MyArrayExample 22 { 23 public string Key { get; set; } 24 public string[] Subsection { get; set; } 25 }
绑定代码:
1 { 2 //1. 绑定到普通类 3 Starship startShipModel = new Starship(); 4 Configuration.GetSection("starship").Bind(startShipModel); 5 6 //2. 绑定到对象 7 User user = new User(); 8 Configuration.GetSection("User").Bind(user); 9 10 //3. 绑定数组到类 11 MyArrayExample myExample = new MyArrayExample(); 12 Configuration.GetSection("json_array").Bind(myExample); 13 14 }
三. 选项模式
1. 声明MyOptions类,与appsetting.json对应。
1 public class MyOptions 2 { 3 public MyOptions() 4 { 5 Option1 = "value1_from_ctor"; 6 } 7 public string Option1 { get; set; } 8 public string Option2 { get; set; } = "555"; 9 }
{
/******************************************************下面是选项模式相关的***************************************************/
"option1": "I am option1",
"option2": "I am option2"
}
2. 然后在Startup类中ConfigureServices中进行选项的相关配置,
3. 在HomeController中进行注入,然后使用即可。
1 //下面是选项系统相关的属性或字段声明 2 private readonly MyOptions _options; 3 public HomeController(IOptions<MyOptions> optionsAccessor) 4 { 5 _options = optionsAccessor.Value; 6 } 7 public IActionResult Index2() 8 { 9 /*************************************** 三.各种配置文件的读取 **********************************************/ 10 11 ViewBag.MyOptions= $"option1 = {_options.Option1}, option2 = {_options.Option2}"; 12 return View(); 13 }
页面展示:
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。