42

ASP.NET Core 自定义配置源 | Beck's Blog

 4 years ago
source link: http://beckjin.com/2019/11/16/aspnet-custom-provider/?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

ASP.NET Core 自定义配置源

发表于 2019-11-16

| 分类于 ASP.NET Core

| 阅读次数: 230

正如大家所知,在 .NET Core 中配置文件改成了 appsettings.json,表面上和 .NET Framework 的 web.configapp.config 好像没有太大的区别,只是一种是 json ,一种是 xml,但其实 .NET Core 的配置体系是一种全新的设计,灵活且具扩展性。这里主要介绍一下在 .NET Core 的配置体系下如何扩展自定义配置源,配置源其实就是配置信息存放的载体,最常用的就是文件类型。

.NET Core 配置体系

在进行自定义配置源介绍前,我们需要先了解一下 .NET Core 中的配置体系。 .NET Core 的配置体系中主要包含 ConfigurationProviderConfigurationSourceConfigurationBuilderConfiguration 几大核心对象。

ConfigurationProvider

实现 IConfigurationProvider 接口,配置源真正提供者,主要提供配置信息的加载与刷新。

ConfigurationSource

实现 IConfigurationSource 接口,提供对应的 ConfigurationProvider 具体实例。

ConfigurationBuilder

实现 IConfigurationBuilder 接口,负责将 ConfigurationSource 添加到配置源集合,再根据配置源集合构建出 ConfigurationRoot 对象,实现 IConfigurationRoot 接口。

Configuration

实现 IConfiguration 接口,Configuration 对象在逻辑上体现出树形化层次结构,配置信息均已键/值对的方式提供使用。

注 : IConfigurationRootIConfigurationSection 均继承于 IConfigurationIConfigurationRoot 表示配置的根节点,IConfigurationSection 则表示配置的非根节点

所以他们之间的关系就是 ConfigurationProvider 实现配置提供,然后通过 ConfigurationSource 构造配置源实例,接着通过 ConfigurationBuilder 将配置源实例 ConfigurationSource 添加到配置源集合中并构造出 ConfigurationRoot,最终以 Configuration 对象提供给程序使用。

relation

默认情况下,Configuration 对象的 Providers 属性包含如下 Provider

providers
  1. ChainedConfigurationProvider:应用程序本身相关配置信息,如:applicationName、contentRoot;
  2. JsonConfigurationProvider:appsettings.json 和 appsettings.Development.json 中的配置信息;
  3. EnvironmentVariablesConfigurationProvider:环境变量的配置信息;
  4. CommandLineConfigurationProvider:命令行输入的配置信息;

这些类型的 Provider 在 .NET Core Web 项目中默认会自动加载,不需要手动配置,当然预置的 Provider 并不止这几种。

自定义配置源

前面提到 .NET Core 的配置体系是具有扩展性的,所以我们可以实现自定义的配置源,比如基于配置中心(如:etcd、apollo、consul 等)的实现,下面将模拟从配置中心获取,先了解整体实现方式,后面也会介绍我们在实际项目中基于 etcd 的实现方案。

创建 ConfigurationProvider

自定义 Provider 需要继承 ConfigurationProvider,然后重写 Load 方法,设置 Data 属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class CustomConfigurationProvider : ConfigurationProvider
{
public override void Load()
{
// 模拟从远程配置中心获取配置信息
using var httpClient = new HttpClient
{
BaseAddress = new Uri("http://localhost:5000")
};

var response = httpClient.GetStringAsync("/api/configs")
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();

if (!string.IsNullOrEmpty(response))
{
Data = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
}
}
}

http://localhost:5000/api/configs 接口返回的 json 字符串,如下:

1
{"name":"beck","company":"mingdao"}

创建 ConfigurationSource

实现 IConfigurationSource 接口,在 Build 方法中返回 CustomConfigurationProvider 实例。

1
2
3
4
5
6
7
public class CustomConfigurationSource : IConfigurationSource
{
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new CustomConfigurationProvider();
}
}

加入 ConfigurationBuilder 配置源列表

添加 IConfigurationBuilder 扩展方法 AddCustom,将 CustomConfigurationSource 加入配置源集合中。

1
2
3
4
5
6
7
public static class CustomConfigurationExtensions
{
public static IConfigurationBuilder AddCustom(this IConfigurationBuilder builder)
{
return builder.Add(new CustomConfigurationSource());
}
}

启动入口添加 AddCustom

Program.cs 中的 ConfigureAppConfiguration 引用自定义配置源:

1
2
3
4
5
6
7
8
9
10
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureAppConfiguration((context, configBuiler) =>
{
configBuiler.AddCustom();
});
webBuilder.UseStartup<Startup>();
});

再次查看 Configuration 对象的 Providers 属性,发现已包含 CustomConfigurationProvider

customConfigurationProvider

然后可通过 Configuration 对象获取对应 key 的内容:

[HttpGet]
public IEnumerable<string> Get()
{
  return new string[] { _configuration["name"], _configuration["company"] };
}

result

以上完成了一个简单的自定义配置源,实际情况会比这复杂些。如果关注过 JsonConfigurationProvider 的配置加载参数,有一个 reloadOnChange 参数用来设置当配置文件有变化时是否重新加载,如果 reloadOnChange 设置为 true,当配置文件变化时不需要重启服务就可以生效,很多时候我们是需要 Provider 具有这个功能的,在接下来介绍的 EtcdConfigurationProvider 中会实现,实现源码 已在 Github 可供参考。

如果对你有帮助就好

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK