特别说明:
1、本系列内容主要基于杨中科老师的书籍《ASP.NET Core技术内幕与项目实战》及配套的B站视频视频教程,同时会增加极少部分的小知识点
2、本系列教程主要目的是提炼知识点,追求快准狠,以求快速复习,如果说书籍学习的效率是视频的2倍,那么“简读系列”应该做到再快3-5倍
本节内容,涉及3.2(P60-P69),7.2(P188-P193),NuGet包
- Microsoft.Extensions.Configuration
- Microsoft.Extensions.Configuration.Json
- Microsoft.Extensions.Configuration.CommandLine
- Microsoft.Extensions.Configuration.EnvironmentVariables
- Microsoft.Extensions.Configuration.Binder
- Microsoft.Extensions.Options
- ...
一、直接读取配置
1 //appsetting.json文件,需设置为“如果较新则复制” 2 { 3 "name": "functionMC", 4 "proxy": { 5 "address": "192.1.1.1", 6 "port": 1088 7 } 8 } 9 10 11 //Program.cs 12 ConfigurationBuilder configBuilder = new ConfigurationBuilder(); 13 configBuilder.AddJsonFile("appsettings.json", optional: false, reloadOnChange:false); 14 IConfigurationRoot config = configBuilder.Build(); 15 16 string name = config["proxy:address"]; 17 Console.WriteLine(name); 18 19 string proxyAddress = config.GetSection("name").Value; 20 Console.WriteLine(proxyAddress);
代码解释:
12-13行:构建ConfigurationBuild对象,并调用该对象的AddJsonFile方法,加载Json配置文件
14行:调用ConfigurationBuild对象的Build方法,构建IConfigurationRoot对象-config,用于读取配置
16行:通过config["key"]方式,读取key值,读取联级key的方式,与config.GetSection一致,"proxy:address"
19行:通过config.GetSection方法,读取key值
补充说明:
①涉及类型: ConfigurationBuild(配置)、IConfigurationRoot(读取)-体现面向接口编程,根据不同的配置源有不同的实现
②13行可以设置其它配置源:
- 从命令行读取:configBuild.AddCommandLine(args);
- 从环境变量读取:configBuild.AddEnvironmentVariables("Test_"),其中Test_为环境变量的前缀,可以实现过滤
- 其它配置源:INI文件、XML文件、Key-per-file文件、用户机密、第三方配置提供程序等
- 当在13行,配置多个数据源时,按Add的添加顺序读取,如果多个配置源设置了相同的key,则后面的key值覆盖前面的key值
- 在ASP.NET Core,已经默认添加了多个配置源,添加顺序为appsettings.json < appsettings.[运行时环境变量].json< 用户机密 < 环境变量 < 命令行
③在VS上设置命令行参数和环境变量的入口,项目右击>属性>调试>打开调试启动配置文件UI。用户机密入口,项目右击>管理用户机密
二、通过选项方式读取
1 //appsettings.json文件 2 { 3 "Smtp": { 4 "Server": "smtp.youzack.com", 5 "UserName": "functionMC", 6 "Password": "hello123" 7 }, 8 "Db": { 9 "DbType": "SQLServer", 10 "ConnectionString": "Data..." 11 } 12 } 13 14 15 //两个与配置Smtp和Db关联的类 16 //SmtpSettings.cs 17 class SmtpSettings 18 { 19 public string Server { get; set; } 20 public string UserName { get; set; } 21 public string Password { get; set; } 22 } 23 24 //DbSettings.cs 25 class DbSettings 26 { 27 public string DbType { get; set; } 28 public string ConnectionString { get; set; } 29 } 30 31 32 //配置、选项绑定,并调用一个方法来读取配置 33 //Program.cs 34 ConfigurationBuilder configBuilder = new ConfigurationBuilder(); 35 configBuilder.AddJsonFile("appsettings.json", optional: false, reloadOnChange:true); 36 IConfigurationRoot config = configBuilder.Build(); 37 38 ServiceCollection services = new ServiceCollection(); 39 services.AddOptions() 40 .Configure<DbSettings>(e=>config.GetSection("Db").Bind(e)) 41 .Configure<SmtpSettings>(e=>config.GetSection("Smtp").Bind(e)); 42 43 services.AddTransient<ReadOptions>(); 44 45 using (var sp = services.BuildServiceProvider()) 46 { 47 while (true) 48 { 49 using (var scope = sp.CreateScope()) 50 { 51 var sp_scope = scope.ServiceProvider; 52 var readOptions = sp_scope.GetRequiredService<ReadOptions>(); 53 readOptions.Read(); 54 } 55 Console.WriteLine("修改appsettings后,按任意键读取最新的配置"); 56 Console.ReadKey(); 57 } 58 } 59 60 61 //读取配置的方法类 62 //ReadOptions.cs 63 class ReadOptions 64 { 65 private readonly IOptionsSnapshot<SmtpSettings> optSmtpSettings; 66 private readonly IOptionsSnapshot<DbSettings> optDbSettings; 67 68 public ReadOptions(IOptionsSnapshot<SmtpSettings> optSmtpSettings, IOptionsSnapshot<DbSettings> optDbSettings) 69 { 70 this.optSmtpSettings = optSmtpSettings; 71 this.optDbSettings = optDbSettings; 72 } 73 74 public void Read() 75 { 76 var smtp = optSmtpSettings.Value; 77 var db = optDbSettings.Value; 78 Console.WriteLine(smtp.UserName); 79 Console.WriteLine(db.DbType); 80 } 81 }
代码解释:
17-29行:定义两个类(选项类),分别映身appsettings的两个属性。SmtpSettings.cs映射Smtp属性,DbSettings.cs映射Db属性,名字一一对应
38行:构建依赖注入的容器
39-41行:注册选项服务AddOptions,并设置“选项类和配置文件属性”之间的映射关系。这样写也可以:services.AddOption;services.Configure<DbSettings>......
43行:将读取配置的类注册为瞬时服务(ReadOptions),这样在后面循环读取配置时,每次都能创建一个新的服务
45-58行:通过服务定位器的方式获取服务(ReadOptions对象),使用了子域方式,稍显复杂,主要目的是测试修改appsettings时的实时更新
63-81行:以依赖注入的方式,注入读取配置的服务,注意不能直接使用SmtpSettings或DbSettings,需要使用IOptions<T>泛型接口
补充说明:
①读取配置的泛型接口,有三种:IOptions<T>(类似单例),IOptionsMonitor<T>(类似范围),IOptionsSnapshot<T>(类似瞬时)。以上案例,改成另外两个,都无法实现配置信息的实时更新。其中IOptions<T>,需要重启应用;IOptionsMonitor<T>,重启应用,或者修改代码,不在Scope中读取
三、在ASP.NET Core中设置和读取配置(本节有补充知识点)
1 //appsettings.json文件 2 { 3 "Smtp": { 4 "Server": "192.1.1.1", 5 "UserName": "functionMC", 6 "Password": "123456" 7 } 8 } 9 10 11 //选项类SmtpSettings.cs 12 public class SmtpSettings 13 { 14 public string Server { get; set; } 15 public string UserName { get; set; } 16 public string Password { get; set; } 17 } 18 19 20 //使用MiniApi方式,直接在Program中设置选项绑定和读取配置 21 var builder = WebApplication.CreateBuilder(args); 22 builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("Smtp")); 23 24 var app = builder.Build(); 25 26 app.MapGet("/", (IConfiguration config,IOptions<SmtpSettings> smtpOptions) => 27 { 28 return $"直接读取:{config["Smtp:UserName"]},选项读取:{smtpOptions.Value.UserName}"; 29 }); 30 31 app.Run();
代码解释:
21行:CreateBuilder完成一系列框架设置,包括配置体系(AddJsonFile,AddOptions等),所以不需要手动设置配置体系,框架自动设置多配置源
22行:绑定选项类和配置属性。在Program中不方便注入,通过调用build的属性Configuration,返回IConfiguration接口读取配置(区别于.NET中的IConfigurationRoot)
26行:通过MiniApi的参数注入两个服务,IConfigurations和IOptions<T>,均由框架自动注册。如果使用控制器,可通过构造函数方式注入
28行:使用两种方式读取配置:直接读取配置、通过选项方式读取配置