一、前言
配置的本质就是字符串的键值对,微软的一系列接口其实就是对这些键值对字符串的抽象。
二、基本类型
2.1、Nuget包
Microsoft.Extensions.Configuration.Abstractions
Microsoft.Extensions.Configuration
2.2、抽象接口
IConfiguration
提供了查询、设置配置项、监控变化等方法
IConfigurationRoot
在IConfiguration接口基础上,增加了 Reload 方法强制从provider中重新加载配置值
IConfigurationSection
对配置节点的抽象
IConfigurationBuilder
根据提供的数据源注册并构建IConfiguration
IConfigurationSource
对数据源的抽象,例如Json、xml、环境变量、内存变量等
IConfigurationProvider
规定了配置项的获取、设置、重载等统一的行为
三、基本配置
注:各种配置方式的目的是在控制台中输出以下内容,如下图:
3.1、加载内存中的配置
需要引入包:Microsoft.Extensions.Configuration
主要方法:builder.AddInMemoryCollection()
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
var memoryData = new Dictionary<string, string>();
memoryData.Add("Student:Code", "10002385");
memoryData.Add("Student:Name", "LiuSan");
builder.AddInMemoryCollection(memoryData);
IConfigurationRoot configurationRoot = builder.Build();
IConfigurationSection configurationSection = configurationRoot.GetSection("Student");
Console.WriteLine($"Code:{configurationSection["Code"]}");
Console.WriteLine($"Name:{configurationSection["Name"]}");
Console.Read();
}
3.2、加载环境变量中的配置
需要引入包:Microsoft.Extensions.Configuration.EnvironmentVariables
主要方法:builder.AddEnvironmentVariables()
环境变量中层级关系使用 __ 代替 :
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddEnvironmentVariables();
IConfigurationRoot configurationRoot = builder.Build();
IConfigurationSection configurationSection = configurationRoot.GetSection("Student");
Console.WriteLine($"Code:{configurationSection["Code"]}");
Console.WriteLine($"Name:{configurationSection["Name"]}");
Console.Read();
}
3.3、加载命令行中的配置
需要引入包:Microsoft.Extensions.Configuration.CommandLine
主要方法:builder.AddCommandLine(args)
命令行中使用--表示配置项,层级关系使用:
主要在docker中使用
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddCommandLine(args);
IConfigurationRoot configurationRoot = builder.Build();
IConfigurationSection configurationSection = configurationRoot.GetSection("Student");
Console.WriteLine($"Code:{configurationSection["Code"]}");
Console.WriteLine($"Name:{configurationSection["Name"]}");
Console.Read();
}
3.4、加载Json中的配置
需要引入包:Microsoft.Extensions.Configuration.Json
主要方法:builder.AddJsonFile("appsettings.json")
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddJsonFile("appsettings.json");
IConfigurationRoot configurationRoot = builder.Build();
IConfigurationSection configurationSection = configurationRoot.GetSection("Student");
Console.WriteLine($"Code:{configurationSection["Code"]}");
Console.WriteLine($"Name:{configurationSection["Name"]}");
Console.Read();
}
3.5、加载xml中的配置
需要引入包:Microsoft.Extensions.Configuration.Xml
主要方法:builder.AddXmlFile("appsettings.xml")
xml中不会读取最外层,所以Section必需从第二层开始
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddXmlFile("appsettings.xml");
IConfigurationRoot configurationRoot = builder.Build();
IConfigurationSection configurationSection = configurationRoot.GetSection("Student");
Console.WriteLine($"Code:{configurationSection["Code"]}");
Console.WriteLine($"Name:{configurationSection["Name"]}");
Console.Read();
}
四、高级配置
4.1、将配置绑定至强对象
需要引入包:Microsoft.Extensions.Configuration.Binder
主要方法:configurationRoot.GetSection("Student").Bind(student)
class Program
{
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddJsonFile("appsettings.json");
IConfigurationRoot configurationRoot = builder.Build();
var student = new Student();
configurationRoot.GetSection("Student").Bind(student);
Console.WriteLine($"Code:{student.Code}");
Console.WriteLine($"Name:{student.Name}");
Console.Read();
}
}
class Student
{
public string Code { get; set; }
public string Name { get; set; }
}
4.2、IOptions
需要引入包:Microsoft.Extensins.Options
需要引入包:Microsoft.Extensions.Options.ConfigurationExtensions
本质其实就是将一个Section配置节点映射到一个实体对象
class Program
{
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddJsonFile("appsettings.json");
IConfigurationRoot configurationRoot = builder.Build();
IServiceCollection services = new ServiceCollection();
services.Configure<WeixinOptions>(configurationRoot.GetSection("WeixinSetting"));
services.AddScoped<IWeixinService, WeixinService>();
var provider = services.BuildServiceProvider();
var weixinService = provider.GetService<IWeixinService>();
string appId = weixinService.AppId;
string token = weixinService.Token;
Console.Read();
}
}
interface IWeixinService
{
string AppId { get; }
string Token { get; }
}
class WeixinService: IWeixinService
{
IOptions<WeixinOptions> _options;
public WeixinService(IOptions<WeixinOptions> options)
{
_options = options;
}
public string AppId { get => _options.Value.AppId; }
public string Token { get => _options.Value.Token;}
}
class WeixinOptions
{
public string AppId { get; set; }
public string Token { get; set; }
}
4.3、热更新
IConfigurationBuilder添加数据源时设置reloadOnChange=true
监听的核心方法:var token = configurationRoot.GetReloadToken();
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddJsonFile("appsettings.json", optional:false, reloadOnChange:true);
IConfigurationRoot configurationRoot = builder.Build();
IConfigurationSection configurationSection = configurationRoot.GetSection("Student");
var token = configurationRoot.GetReloadToken();
ChangeToken.OnChange(() => configurationRoot.GetReloadToken(), () =>
{
Console.WriteLine("配置发生改变了...");
Console.WriteLine($"Code:{configurationSection["Code"]}");
Console.WriteLine($"Name:{configurationSection["Name"]}");
});
Console.Read();
}
五、总结
配置就是key-value键值对字符串
IConfiguration和IConfigurationRoot是对键值对的抽象
IConfigurationBuilder用于构建IConfiguration和IConfigurationRoot
IConfigurationSource是对数据源的抽象
IConfigurationProvider将不同来源的IConfigurationSource 转为统一的模型
IOptions方便将不同的配置节点(Path)映射为对应的强类型对象
IConfigurationBuilder添加多个数据源(IConfigurationSource)后,如果key重名,则以最后一个配置为准(覆盖前面)