在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在前面的章节中,我们知道新版的MVC程序抛弃了原来的web.config文件机制,取而代替的是config.json,今天我们就来深入研究一下配置文件的相关内容。 基本用法 新版的配置信息机制在Microsoft.Framework.ConfigurationModel命名空间下进行了重写,重写以后不仅支持XML格式,还支持json、ini、环境变量等。在模板示例程序中Startup类的构造函数内如,有如下语句: // Setup configuration sources. Configuration = new Configuration() .AddJsonFile("config.json") .AddEnvironmentVariables(); 该语句的作用是将config.json文件以及环境变量信息加入到配置信息容器里,以便进行读取。而读取的时候则可以通过集合索引的形式或Get方法进行读取,示例如下: var path = Configuration["Path"]; var path = Configuration.Get("Path"); 其中,多层级key键的读取,需要在多个层级名称之间用冒号分割即可,示例如下: var connString = Configuration.Get("Data:DefaultConnection:ConnectionString"); 通过上述几段代码可以看出,该配置示例并不是全局实例,所以要想在别的地方也读取这些信息,就需要将该实例保存在一个全局静态变量上。 架构设计 新的配置信息处理机制,在重写以后,更加轻量级,而且是进行跨平台使用,可以从多个数据源获取配置信息,而不必在拘泥于.config文件,而且甚至可以为不同的环境(开发、测试、生产)设置不同的配置信息。整个配置机制的各个重要实体见下图: 我们来一一讲述一下,这些类的具体作用: 1. 2. 3. 4. 5. 在Microsoft.Framework.ConfigurationModel命名空间下,目前有6种不同类型的配置源类型可以使用,分别如下: 1. 2. 3. 4. 5. 6. 详细用法 首先,由于配置系统是多实例型的,所以每次使用之前都要先声明一个示例,代码如下: IConfiguration configuration = new Configuration(); 添加MemoryConfigurationSource 由于在IConfigurationSourceContainer上没有为MemoryConfigurationSource定义快速加载配置信息的扩展方法,所以如果想加载这种类型的配置信息,则需要按照如下形式进行添加: ((IConfigurationSourceContainer)Configuration) .Add(new MemoryConfigurationSource( new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("mem-key1", "mem-value1"), new KeyValuePair<string, string>("mem-key2", "mem-value2") })); //取值方式 var someConfiguration1 = Configuration["mem-key1"]; var someConfiguration2 = Configuration.Get("mem-key2"); 添加IniFileConfigurationSource IniFileConfigurationSource类型的配置信息可以通过扩展方法进行加载,代码如下: var configuration = new Configuration().AddIniFile("path\\to\\your\\configuration-ini-file.ini"); 其中ini文件的格式模板如下: [ini-sec] ini-key1=value-a ini-key2=value-b [ini-sec2] ini-key1=value-c ini-key2=value-d 这里的[ini-sec]是自定义的配置节名称,每个配置节下面可以配置多个key/value项。取值方式和基本示例中的一样,层级之间(本例是配置节和key之间)要用冒号分割,示例如下: var someConfiguration1 = Configuration["ini-sec:ini-key1"]; var someConfiguration2 = Configuration.Get("ini-sec2:ini-key2"); 添加CommandLineConfigurationSource 在程序使用k run命名进行时传入的参数,可以通过该配置源进行读取,或者你也可以通过 var configuration = new Configuration().AddCommandLine(new string[] { "key1=value1", "key2=value2", "@key3=value3" }); 上述示例中的每个字符串都要是key/value格式,可以使用少于的特殊符号比如$、/等。 针对这些key值,你也可以使用带有 var mappings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "key1", "tom1" }, { "key2", "tom2" }, }; 由于当前没有针对CommandLineConfigurationSource类的扩展方法,所以我们还是需要自己实例化该类,并添加到配置容器中,代码如下: ((IConfigurationSourceContainer)Configuration).Add(new CommandLineConfigurationSource(commandLineArguments, switchMappings: mappings)); 执行上述代码以后,在获取配置值的时候,如下两个key的值是一样的: var value1 = Configuration.Get("key1"); var value2 = Configuration["tom1"]; // tom1这个key的值其实就key1的值,因为tom1是key1的映射 在映射的时候,新的映射key字符串里不能包括“/”字符,否则会报异常同样的key不能传入两次,否则也会报异常加载配置信息时,如果有重复key,则后一个key的值会覆盖前一个key的值。加载CommandLine配置信息时,如果一个key字符串以-作为前缀,那么就必须利用switchMapping将一个新key映射到旧key上,否则就会出错。 添加EnvironmentVariablesConfigurationSource
取值方式如下: var someConfiguration1 = Configuration["env_var_key1"]; var someConfiguration2 = Configuration["env_var_key2"]; 另外,该配置源也支持Azure环境变量和连接字符串,所以你也可以在Azure界面里设置MSSQL、MYSQL、以及自定义链接字符串等等,但这些链接字符串需要以如下字符串开头: 1.MySQL => 2.MS SQL => 3.SQL Azure DB => 4.Custom DB => 举例来说,定义一个开发环境的key/value如下: Key => SQLCONNSTR_devlocal Value => Server=localhost;Database=test_db;Trusted_Connection=True; 通过AddEnvironmentVariables()的形式load完信息以后,我们则可以通过如下方式来访问这项信息: var connString = Configuration["Data:devlocal:ConnectionString"]; 也就是说,在Azure里,环境变量的key会转换成Data:自定义标识符:ConnectionString这样的格式。如果你的key不是自定义key(以 var providerName = Configuration["Data:devlocal:ProviderName"]; /// 返回:System.Data.SqlClient
((IConfigurationSourceContainer)Configuration).Add(new EnvironmentVariablesConfigurationSource("Data:")); 这样,再获取信息的时候,key值里的Data:就可以省略了,示例如下: var conn1 = Configuration["devlocal:ConnectionString"]; var conn2 = Configuration["devlocal:ProviderName"]; 添加JsonConfigurationSource 在文章的开头,我们看到了json配置文件的加载,加载该文件只需要使用 比如,如果你的config.json文件内容如下: { "Data": { "DefaultConnection": { "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-WebApplication1-64357659-de50-4b1e-b005-30310e7ee1ef;Trusted_Connection=True;MultipleActiveResultSets=true" } }, "EntityFramework": { "ApplicationDbContext": { "ConnectionString": "Data:DefaultConnection:ConnectionString" } } } 那你就可以利用如下方式来访问链接字符串: var conn = Configuration["Data:DefaultConnection:ConnectionString"]; 添加XmlconfigurationSource
如果你的配置文件test.xml的内容如下: <root> <key1>Jsinh</key1> <key2 subkey2="Hello world" /> </root> 获取形式,则稍有有些区别(会忽略根节点root): var s1 = Configuration["key1"]; // 返回Jsinh var s2 = Configuration["key2:subkey2"]; // 返回 Hello world 但是要注意,通用的key不能重复声明,下面的文件在读取的时候就会出错。 <root> <key1>Jsinh</key1> <key2 subkey2="Hello world" /> <key2 subkey2="Hello world again" /> </root> 敏感信息配置(RC版新增功能) 在RC版发布以后,微软又新增了一种敏感信息配置实现,程序集为 Windows: %APPDATA%\microsoft\UserSecrets\<applicationId>\secrets.json Linux: ~/.microsoft/usersecrets/<applicationId>\secrets.json Mac: ~/.microsoft/usersecrets/<applicationId>\secrets.json 我们来举例操作一下,首先,右键解决方案选择 { "userSecretsId": "aspnet5-WebDemo01-20150430014447", "webroot": "wwwroot", "version": "1.0.0-*", } 接着会自动打开 { "AA": { "BB": "CC" } } 然后,我们在project.json文件里引用了上述程序集,再通过配置文件的统一方式进行注册,代码如下: Configuration = new Configuration() .AddJsonFile("config.json") .AddEnvironmentVariables() .AddUserSecrets(); // AddUserSecrets是添加敏感信息的扩展方法 然后就可以想普通的调用方法一下调用了,示例如下: var data = Configuration["AA:BB"]; // 结果:CC 通过这种方式,我们就可以将生产环境的配置信息放在隐私的位置了。 自定义配置源 通过以上示例以及查看其架构设计机制,我们可以发现,其实我们还可以自定义自己的配置源,比如我想从数据库中读取响应的配置信息,那我们只要定义一个DBConfigurationSource,并继承于ConfigurationSource即可,实现响应的Load重载即可。 public class DBConfigurationSource : BaseConfigurationSource { public override void Load() { // 读取数据库所有的key/value,并将其赋值给IDictionary<string, string>类型的Data数据 } } 如果你不把数据保存在Data属性里,那么你还要实现如下几个重载,以便从自己的私有数据集合里获取响应的值,比如从缓存中获取,示例如下: public class DBConfigurationSource : BaseConfigurationSource { public override void Load() { // 读取数据库所有的key/value,保存在私有变量_data中 } public override void Set(string key, string value) { // 更新数据库key对应的值 // base.Set(key, value); } public override bool TryGet(string key, out string value) { // 从私有变量_data中获取key对应的value // return base.TryGet(key, out value); } public override IEnumerable<string> ProduceSubKeys(IEnumerable<string> earlierKeys, string prefix, string delimiter) { // 私有变量_data中,根据自己的机制返回响应的SubKeys // return base.ProduceSubKeys(earlierKeys, prefix, delimiter); } } 实现完上述类以后,再为自己创建一个扩展方法用于添加DB配置信息,代码如下: public static class CatsConfigurationExtensions { public static IConfigurationSourceContainer AddDBConfiguration(this IConfigurationSourceContainer configuration) { configuration.Add(new DBConfigurationSource()); return configuration; } } 就可以通过.AddDBConfiguration()来添加DB配置源了。 注意,DB配置源需要使用数据库连接字符串,这一点需要注意(获取可以先从json配置文件获取连接字符串,然后再添加该配置源)。 配置信息遍历 在默认的配置源实现中,所有的类都继承于ConfigurationSource,并且将信息数据保存在Data属性中,所以如果要遍历这些数据,则需要将其转换为ConfigurationSource类型才能使用,示例代码如下: foreach (var o in Configuration as Configuration) { var source = o as ConfigurationSource; foreach (var key in source.Data.Keys) { Console.WriteLine(key + ":" + source.Data[key]); } } 配置信息直接转换为实体类 在 public static IServiceCollection Configure<TOptions>(this IServiceCollection services, IConfiguration config, int order = -1000, string optionsName = ""); 举个例子,如果我们定义如下一个实体: public class AppSettings { public string SiteTitle { get; set; } } 然后在 { "AppSettings": { "SiteTitle": "WebDemo01" } } 那么通过在 services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings")); 用的时候,使用 var appSettings = app.ApplicationServices.GetRequiredService<IOptions<AppSettings>>().Options; 注意事项: 在配置信息里,所有的key都是不区分大小写的,即key和KEY是一样的。如果多个配置源有重复的key,则以后最后添加的配置源中的key所对应的值为准。 参考1:https://github.com/aspnet/Configuration |
请发表评论