一、配置环境
1.1 配置系统的基本使用
在.NET Framework中是将配置信息放在Web.config文件中,修改配置只需要修改配置文件的内容就可。但是当项目变复杂之后,这种简单的配置就显得力不从心。.NET Core中提供了丰富的配置源,包括文件(JSON、XML、INI等)、注册表、环境变量、命令行。Azure Key Vault等,配置系统也支持自定义配置源。
.NET Core读取配置也有很多方式。可以通过IConfigurationRoot读取配置,也可以通过绑定方式把配置读取为一个对象
注意:因为程序在运行的时候默认加载.exe文件同文件夹下的配置文件,而不是项目中的Config.json文件,所以我们需要把Config.json文件设置为生成项目的时候自动复制到生成目录。 如何手动读取配置?
1.2 使用选项方式读取配置
使用选项方式读取配置是.NET Core中推荐的方式,因为他不仅和依赖注入机制结果得更好,而且它可以实现配置修改后自动刷新。
由于使用选项方式读取配置的时候,需要和依赖注入一起使用,因此通常需要创建一个类用于获取注入的选项值。但是接收选项注入的对象的类型不能直接使用DbSettings、SmtpSettings,而要使用IOptions<T>,IOptionsMonitor<T>,IOptionsSnapshot<T>。那么三者有何区别呢?
IOptions<T>:在配置改变后,我们不能读取新的值,必须重启程序。
IOptionsMonitor<T>:配置改变后,可以读到新的值。
IOptionsSnapshot<T>:配置改变后,可以读到新的值,与上者不同的是,上者在同一范围内会保持一致性。
(比如A,B代码都读取同一个配置,在A运行后B运行前更改了配置,使用IOptionsMonitor的话A读取的是旧值,B是新值,使用IOptionsSnapshot的话A,B都是旧值,只有再次进入这个范围才会是新值)
/*
* 注入服务到容器
*/
ConfigurationBuilder configBuilder = new ConfigurationBuilder();
configBuilder.AddJsonFile("config.json", optional: false, reloadOnChange: true);
IConfigurationRoot config = configBuilder.Build();
ServiceCollection services = new ServiceCollection();
//使用AddOptions方法注册与选项相关的服务
services.AddOptions()
.Configure<DbSettings>(e => config.GetSection("DB").Bind(e)) //把DB节点内容绑定到DbSettings模型对象上
.Configure<SmtpSettings>(e => config.GetSection("Smtp").Bind(e)); //把Smtp节点内容绑定到SmtpSettings模型对象上
services.AddTransient<Demo>(); //只能注册为瞬态服务,因为在Demo类中用的IOptionsSnapshot<T>生命周期是 "范围"
using (var sp = services.BuildServiceProvider())
{
while (true) //设置无限循环,方便一直反复测试,修改配置文件
{
using (var scope = sp.CreateScope()) //因为IOptionsSnapshot<T>会在新范围加载配置,所以每次循环都创建一个范围
{
var spScope = scope.ServiceProvider;
var demo = spScope.GetRequiredService<Demo>();
demo.Test();
}
Console.WriteLine("可以改配置了");
Console.ReadKey();
}
}
class Demo
{
private readonly IOptionsSnapshot<DbSettings> optDbSettings;
private readonly IOptionsSnapshot<SmtpSettings> optSmtpSettings;
//通过构造方法注入IOptionsSnapshot<DbSettings>和IOptionsSnapshot<SmtpSettings>两个服务
public Demo(IOptionsSnapshot<DbSettings> optDbSettings,
IOptionsSnapshot<SmtpSettings> optSmtpSettings)
{
this.optDbSettings = optDbSettings;
this.optSmtpSettings = optSmtpSettings;
}
public void Test()
{
var db = optDbSettings.Value;//获取具体配置模型对象的值
Console.WriteLine($"数据库:{db.DbType}, {db.ConnectionString}");
var smtp = optSmtpSettings.Value;//获取具体配置模型对象的值
Console.WriteLine($"Smtp:{smtp.Server}, {smtp.UserName}, {smtp.Password}");
}
}
//建立两个模型类
public class DbSettings
{
public string DbType { get; set; }
public string ConnectionString { get; set; }
}
public class SmtpSettings
{
public string Server { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
}
运行结果如下:
此时不要关闭程序,打开程序生成目录下的config.json文件(bin文件夹内),修改文件内容后保存,再点击Enter键,让程序执行下一次循环操作。
可以发现修改了数据库名称,再次运行的时候自动输出了更改后的配置。但是有一个注意点:修改配置文件信息的时候不能直接修改项目中的文件,因为这是源文件,程序运行中下载的是程序生成文件夹(bin文件夹)下的配置文件。
1.3 从命令行读取配置
从命令行读取配置特别适合容器化的运行环境
直接运行时为空结果,因为这是命令行读取配置方式。如下找到程序的.exe文件,使用cmd进入命令行后手动输入配置信息即可读出。
Visual Studio中提供了可以设置命令行参数的选项,避免手动打开cmd的麻烦。