配置系统
1.1配置系统
说明:
- 传统的Web.config配置的缺点
- 为了兼容,仍然可以使用Web.config和ConfigurationManager类,但不推荐
- .NET 中的配置系统支持丰富的配置源,包括文件(JSON,XML,ini等)注册表,环境变量,命令行,Azure Key Vault等,还可以配置自定义配置源。可以跟踪配置的改变,可以按照优先级覆盖。
1.2 JSON文件配置
- 创建一个JSON文件,文件名随意,比如Config.json,设置“如果较新则复制”.
- NuGet 安装 Microsoft.Extensions.Configuration和Microsoft.Extensions.Configuration.Json
- 编写代码,先用简单的凡是读取配置
1.21 读取原始配置
首先先下载包
PM> Install-Package Microsoft.Extensions.Configuration
PM> Install-Package Microsoft.Extensions.Configuration.Json
//optional 参数代表这个文件是否可选,初学时,建议 optional 设置为 false,
//这样写错的话能够及时发现。
//reloadOnChange 参数表示如果文件修改了,是否重新加载配置
ConfigurationBuilder configBuilder =new ConfigurationBuilder();
configBuilder.AddJsonFile(
"config.json", optional: false, reloadOnChange: false);
IConfigurationRoot configRoot = configBuilder.Build();
string name = configRoot ["name"];
string proxyAddress = configRoot .GetSection("proxy:address").Value;
绑定读取配置(*)
-
可以绑定一个类,自动完成配置的读取。
- Nuget安装:Microsoft.Extensions.Configuration.Binder
PM> Install-Package Microsoft.Extensions.Configuration.Binder
-
Server server=configRoot.GetSection(“prixy”).Get< Server>()
代码
代码:
internal class Program
{
static void Main(string[] args)
{
//optional参数代表这个文件是否可选,初学时,建议optional设置为false,
//这样写错的话能够及时发现。
//reloadOnChange 参数表示如果文件修改了,是否重新加载配置
ConfigurationBuilder configBuilder = new ConfigurationBuilder();
configBuilder.AddJsonFile(
"config.json", optional: false, reloadOnChange: true);
IConfigurationRoot configRoot = configBuilder.Build();
/**
* 方法1读取数据
string name = configRoot["name"];
string proxyAddress = configRoot.GetSection("proxy:address").Value;
Console.WriteLine($"{name},{proxyAddress}"); */
/*
* //方法2读取数据
Proxy proxy = configRoot.GetSection("proxy").Get<Proxy>();
Console.WriteLine(proxy.Port);
Console.WriteLine(proxy.Address);
Config config = configRoot.Get<Config>();
Console.WriteLine(config.Name);Console.WriteLine(config.Age);
Console.WriteLine(config.Proxy.Address);
*/
}
}
class Config
{
public string Name { get; set; }
public string Age { get; set; }
public Proxy Proxy { get; set; }
}
class Proxy
{
public string Address { get; set; }
public int Port { get; set; }
}
用法:
- 推荐使用选项方式读取,和DI结合更好,且更好利用“reloadonchange”机制。
- NuGet安装:Microsoft.Extensions.Options、Microsoft.Extensions.Configuration.Binder,当然也需要Microsoft.Extensions.Configuration、Microsoft.Extensions.Configuration.Json。
- 读取配置的时候,DI要声明IOptions、IOptionsMonitor、IOptionsSnapshot等类型。IOptions不会读取到新的值;和IOptionsMonitor 相比, IOptionsSnapshot会在同一个范围内(比如ASP.NET Core一个请求中)保持一致。建议用IOptionsSnapshot。
方法3
代码:
TestController:
class TestController
{
private readonly IOptionsSnapshot<Config> opConfig;
public TestController(IOptionsSnapshot<Config> opConfig)
{
this.opConfig = opConfig;
}
public void test()
{
Console.WriteLine(opConfig.Value.Age);
Console.WriteLine("****************");
Console.WriteLine(opConfig.Value.Name);
}
}
Test2类
class Test2
{
private readonly IOptionsSnapshot opProxy;
public Test2(IOptionsSnapshot opProxy)
{
this.opProxy = opProxy;
}
public void test()
{
Console.WriteLine(opProxy.Value.Port);
Console.WriteLine("****************");
Console.WriteLine(opProxy.Value.Address);
}
}
Program+接受类:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Security.Cryptography.X509Certificates;
namespace Config1
{
internal class Program
{
static void Main(string[] args)
{
//方法 3 使用依赖注入
ServiceCollection services = new ServiceCollection();
services.AddScoped<TestController>();
services.AddScoped<Test2>();
//optional 参数代表这个文件是否可选,初学时,建议 optional 设置为 false,
//这样写错的话能够及时发现。
//reloadOnChange 参数表示如果文件修改了,是否重新加载配置
ConfigurationBuilder configBuilder = new ConfigurationBuilder();
configBuilder.AddJsonFile(
"config.json", optional: false, reloadOnChange: true);
IConfigurationRoot configRoot = configBuilder.Build();
//将其值获取
services.AddOptions()
.Configure(e => configRoot.Bind(e))
//新的直接添加进去
.Configure(e => configRoot.GetSection("proxy").Bind(e));
/**
方法 1 读取数据
string name = configRoot["name"];
string proxyAddress = configRoot.GetSection("proxy:address").Value;
Console.WriteLine($"{name},{proxyAddress}"); */
/*
//方法 2 读取数据
Proxy proxy = configRoot.GetSection("proxy").Get();
Console.WriteLine(proxy.Port);
Console.WriteLine(proxy.Address);
Config config = configRoot.Get();
Console.WriteLine(config.Name);
Console.WriteLine(config.Age);
Console.WriteLine(config.Proxy.Address);
*/
//方法 3
using (var sp = services.BuildServiceProvider())
{
var c = sp.GetRequiredService();
c.test();
Console.WriteLine("----------"); var c2 = sp.GetRequiredService(); c2.test();
}
}
}
class Config
{
public string Name { get; set; }
public string Age { get; set; }
public Proxy Proxy { get; set; }
}
class Proxy
{
public string Address { get; set; }
public int Port { get; set; }
}
}
1.3 命令行配置
- 配置框架还支持从命令行参数,环境变量等地方读取。
- NuGet安装 Microsoft.Extensions.Configuration.CommandLine。
- configBuilder.AddCommandLine(args)
- 参数支持多种格式,比如:server=127.0.0.1、–server=127.0.0.1、–server 127.0.0.1(注意在键值之间加空格)、/server=127.0.0.1、/server 127.0.0.1(注意在键值之间加空格)。格式不能混用。
- 调试的时候,VS中简化命令行传参数的方法。
1.31 扁平化配置
-
对于环境变量、命令行等简单的键值对结构,如果想要进行复杂结构的配置,需要进行“扁平化处理”。对于配置的名字需要采用“层级配置”。例如:a: b:c。对于数字这样配置:a: b:c:0、 a: b:c:1、 a: b:c:2。
-
如:name=lzh age=18 proxy:address=hunan proxy:port=8080
proxy:ids:0=1 proxy:ids:1=2
-
1.32环境变量配置
1、NuGet安装:Microsoft.Extensions.Configuration.EnvironmentVariables。
2、然后configurationBuilder. AddEnvironmentVariables()
AddEnvironmentVariables() 有无参数和有prefix参数的两个重载版本。无参数版本会把程序相关的所有环境变量都加载进来,由于有可能和系统中已有的环境变量冲突,因此建议用有prefix参数的AddEnvironmentVariables()。读取配置的时候,prefix参数会被忽略。
3、VS中调试时,避免修改系统环境变量,直接在VS中设置环境变量的方法。
1.33其他配置源
1、还支持ini、XML等格式的配置源,如果想用查询文档即可。
2、还支持在运行时、调试时加载不同的JSON文件;
3、还内置或者第三方支持中心化配置服务器,比如使用Apollo、Nacos等开源服务器,或者使用Azure、阿里云等的配置服务。具体看文档即可。
1.4开发自己的配置
1.41 开发自定义配置提供者的步骤
- 开发一个直接或者间接实现IConfigurationProvider接口的类XXXConfigurationProvidder,一般继承自ConfigurationProvider。如果是从文件读取,可以继承自FileConfigurationProvider。重写Load方法,把"扁平化数据"舍之道Data属性即可
- 在开发一个实现了IConfigurationSource接口的类XXXConfigurationSource。如果是从文件读取,可以继承自FileConfigurationSource。在Build方法中返回上面的ConfigurationProvider对象
- 然后使用即可,configurationBuilder.Add(new ConfigurationSource())即可。为了简化使用,一般提供一个IConfigurationBuilder的拓展方法
- 整体流程:编写ConfigurationProvider类实际读取配置;编写ConfigurationSource在Build中返回ConfigurationProvider对象;把ConfigurationSource对象加入IConfigurationBuilder
1.42 开发Web.config提供者
- .NET Core中不建议使用.NET Framework里的Web.config;不过仍然继续提供了ConfigurationManager了,不过没有官方支持通过新的Configuration框架读取的方式。我们来实现一个。能够读取Web.config里的connectionStrings和appSettings的内容 。没用过Web.config也没关系
- 这个项目主要意义还是展示如何编写自定义配置提供者,实用意义不大,主要是为了下一个更实用的配置提供者做知识储备