十年河东,十年河西,莫欺少年穷
学无止境,精益求精
本篇提供几种读取配置文件的方式,从简到难,步步加深
1、新建控制台程序
1.1、新增一个名称为application.json的配置文件
application.json
{ "name": "杰克", "sex": "男", "address": { "country": "美国", "city": "纽约", "port": "181" } }
2、简单读取模式
2.1、项目引用 Microsoft.Extensions.Configuration 和 Microsoft.Extensions.Configuration.Json
static void Main(string[] args) { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddJsonFile("application.json", true, true); var ConfigRoot = builder.Build();//根节点 //简单读取 simple(ConfigRoot); } static void simple(IConfigurationRoot ConfigRoot) { //Microsoft.Extensions.Configuration; //Microsoft.Extensions.Configuration.Json var name = ConfigRoot["name"]; var country = ConfigRoot.GetSection("address:country").Value; var city = ConfigRoot.GetSection("address:city").Value; Console.WriteLine(name); Console.WriteLine(country); Console.WriteLine(city); }
3、选项模式读取
3.1、项目引用 Microsoft.Extensions.Configuration.Binder
static void Main(string[] args) { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddJsonFile("application.json", true, true); var ConfigRoot = builder.Build();//根节点 //选项模式 bindCls(ConfigRoot); } static void bindCls(IConfigurationRoot ConfigRoot) { //Microsoft.Extensions.Configuration.Binder var adrs = ConfigRoot.GetSection("address").Get<addressDto>(); Console.WriteLine("选项模式读取:"+adrs.country); Console.WriteLine("选项模式读取:" + adrs.city); Console.WriteLine("选项模式读取:" + adrs.port); //选项模式 读取根节点 var root = ConfigRoot.Get<rootDto>(); Console.WriteLine("选项模式读取:" + root.name); }
选项模式读取是将json转化为实体类,因此我们还需要如下实体
public class rootDto { public string name { get; set; } public string sex { get; set; } public addressDto address { get; set; } } public class addressDto { public string country { get; set; } public string city { get; set; } public int port { get; set; } //Json中为字符串,框架会做自动类型转换 }
4、IOptions 模式读取【此方式支持依赖注入】
4.1、项目引用 Microsoft.Extensions.Options
ASP.NET Core引入了Options模式,使用类来表示相关的设置组。简单的来说,就是用强类型的类来表达配置项,这带来了很多好处。
初学者会发现这个框架有3个主要的面向消费者的接口:IOptions<TOptions>、IOptionsMonitor<TOptions>以及IOptionsSnapshot<TOptions>。
这三个接口初看起来很类似,所以很容易引起困惑,什么场景下该用哪个接口呢?
关于三种接口应该用哪个的问题,请参考: https://www.cnblogs.com/wenhx/p/ioptions-ioptionsmonitor-and-ioptionssnapshot.html
杨中科老师给的建议是使用IOptionsSnapshot
创建如下实体类及Options选项类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class rootDto { public string name { get; set; } public string sex { get; set; } public addressDto address { get; set; } } public class addressDto { public string country { get; set; } public string city { get; set; } public int port { get; set; } //Json中为字符串,框架会做自动类型转换 } public class OptionsCls { private readonly IOptionsSnapshot<rootDto> options; private readonly IOptionsSnapshot<addressDto> adsOptions; public OptionsCls(IOptionsSnapshot<rootDto> options, IOptionsSnapshot<addressDto> adsOptions) { this.options = options; this.adsOptions = adsOptions; } public void GetValue() { Console.WriteLine("========================================"); Console.WriteLine(options.Value.name); Console.WriteLine(options.Value.sex); } public void GetAdsValue() { Console.WriteLine("========================================"); Console.WriteLine(adsOptions.Value.country); Console.WriteLine(adsOptions.Value.city); } }View Code
其中OptionsCls用来被注入到main函数
static void Main(string[] args) { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddJsonFile("application.json", true, true); var ConfigRoot = builder.Build();//根节点 //Options 模式 optionsCls(ConfigRoot); } static void optionsCls(IConfigurationRoot ConfigRoot) { ServiceCollection services = new ServiceCollection(); //Microsoft.Extensions.Options services.AddOptions().Configure<rootDto>(A => ConfigRoot.Bind(A)); services.AddOptions().Configure<addressDto>(A => ConfigRoot.GetSection("address").Bind(A)); services.AddScoped<OptionsCls>(); using (ServiceProvider provider = services.BuildServiceProvider()) { var dto = provider.GetRequiredService<OptionsCls>(); dto.GetAdsValue(); dto.GetValue(); } }
上述代码重点部分为:
services.AddOptions().Configure<rootDto>(A => ConfigRoot.Bind(A)); services.AddOptions().Configure<addressDto>(A => ConfigRoot.GetSection("address").Bind(A));
第一句代码可以理解为将整个配置文件映射为 rootDto类,第二句代码可以理解为将address接点下的json内容映射为 assressDto类
简单贴出Options模式运行如下:
5、通过 JObject 自定义配置文件读取 【自己造轮子】
5.1、项目引入 Newtonsoft.Json
为了测试自定义方法的有效性,我们将配置文件复杂化,如下
{ "name": "杰克", "sex": "男", "address": { "country": "美国", "city": "纽约", "port": "181", "cart": { "cat": "猫", "TomCat": { "sex": "男", "name": "Tom", "frids": [1,2,3] } } } }
自定义配置文件主方法:
public class ConfigCommon { static ConfigCommon() { #if DEBUG //调试环境 读取 application.json File = "application.json"; string str = System.IO.File.ReadAllText(Environment.CurrentDirectory + "\\" + File); objx = JsonConvert.DeserializeObject<JObject>(str); #else // 发布后环境 读取 appsettings.json File = "appsettings.json"; string str = System.IO.File.ReadAllText(Environment.CurrentDirectory + "\\" + File); objx = JsonConvert.DeserializeObject<JObject>(str); #endif } public static string File { get; set; } public static JObject objx; public static object Get(params string[] Keys) { var obj = objx; JToken jobs = null; for (int i = 0; i < Keys.Length; i++) { string item = Keys[i]; if (i == 0) { jobs = obj[item]; } else if (i != 0 && i != Keys.Length - 1) { jobs = jobs[item]; } else { return jobs.Value<object>(item); } } return null; } }
根据配置文件,创建如下实体
public class TomCatDto { public string sex { get; set; } public string name { get; set; } public object frids { get; set; } }
注意: frids 要定义为object
Main 方法
static void Main(string[] args) { var name = ConfigCommon.Get("address", "cart","TomCat", "name"); if (name != null) { Console.WriteLine(name.ToString()); } var arys = ConfigCommon.Get("address", "cart", "TomCat", "frids"); Console.WriteLine("============================"); if (arys != null) { var lst = ((JArray)arys).ToObject<List<int>>(); ; foreach (var item in lst) { Console.WriteLine("读取数组的值为:"+item); } } Console.WriteLine("============================"); IEnumerable<JToken> TomModels = (IEnumerable<JToken>)ConfigCommon.Get("address", "cart", "TomCat"); foreach(var item in TomModels) { Console.WriteLine(item.GetType()); Console.WriteLine(item.ToString()); } Console.Read(); }
运行结果
需要注意的是,上述自定义方法读取值为字符串的属性很简单,但是读取数组,对象等需要在调试中进行类型转化。
例如数组的读取
var arys = ConfigCommon.Get("address", "cart", "TomCat", "frids"); Console.WriteLine("============================"); if (arys != null) { var lst = ((JArray)arys).ToObject<List<int>>(); ; foreach (var item in lst) { Console.WriteLine("读取数组的值为:"+item); } }
调试过程中,得到的arys的真实类型为 JArray ,但方法的返回值为object ,因此我们需要根据调试的动态类型进行强制转换,然后再转为我们常用的数组类型等
关于我扩展的这个自定义方法,对于读取字符串还是比较完美的,复杂类型需要调试过程中进行类型转化。
@天才卧龙的博客
标签:Console,string,配置文件,public,WriteLine,var,ConfigRoot,Net5,控制台 From: https://www.cnblogs.com/chenwolong/p/net5config.html