C# IConfiguration文件提供者 C#如何实现自定义的配置文件源

来源:这里教程网 时间:2026-02-21 17:42:07 作者:

为什么 IConfigurationBuilder.AddXxx() 不直接接受自定义文件路径

因为

IConfigurationBuilder
的内置方法(如
AddJsonFile()
AddXmlFile()
)底层依赖
IFileProvider
FileConfigurationProvider
,它们默认只处理物理文件系统或嵌入资源。若想加载非标准位置(如数据库、HTTP API、加密 ZIP 内的 config.json),不能靠改参数绕过,必须实现自己的
ConfigurationProvider
子类。

如何写一个最简可用的自定义 ConfigurationProvider

核心是继承

ConfigurationProvider
并重写
Load()
方法,把数据转成
IDictionary<string string></string>
格式(键用冒号分隔,如
"ConnectionStrings:Default"
)。

不要在构造函数里加载数据,
Load()
才是唯一被调用的入口
务必调用
Data = new Dictionary<string string>(StringComparer.OrdinalIgnoreCase)</string>
初始化基类字段
若需热重载(如监听文件变化),还需实现
IChangeToken
并重写
GetReloadToken()

示例:从字符串 JSON 加载

public class JsonStringConfigurationProvider : ConfigurationProvider
{
    private readonly string _json;
    public JsonStringConfigurationProvider(string json) => _json = json ?? throw new ArgumentNullException(nameof(json));
    public override void Load()
    {
        Data = JsonSerializer.Deserialize<Dictionary<string, string>>(_json)
               ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
    }
}

怎样注册自定义 provider 到 IConfigurationBuilder

不能直接用

AddProvider()
传实例(会丢失生命周期管理),应封装为扩展方法,内部调用
builder.Add(new YourProvider())

扩展方法签名必须是
this IConfigurationBuilder builder
若 provider 依赖服务(如
HttpClient
),需通过
builder.Services
注册,并在 provider 构造中接收
IOptionsMonitor<t></t>
IServiceProvider
注意加载顺序:自定义 provider 在
AddJsonFile()
后注册,其值会覆盖前面同名 key

示例注册方式:

public static class ConfigurationBuilderExtensions
{
    public static IConfigurationBuilder AddJsonString(this IConfigurationBuilder builder, string json)
    {
        return builder.Add(new JsonStringConfigurationProvider(json));
    }
}
// 使用
var config = new ConfigurationBuilder()
    .AddJsonString("{\"App:Version\":\"1.2.0\"}")
    .Build();

常见踩坑点:Key 命名与层级解析不一致

配置系统对 key 的解析规则和 JSON 对象结构不是 1:1 映射。例如

{"Logging": {"LogLevel": {"Default": "Information"}}
} 会被展开为
Logging:LogLevel:Default = "Information"
,但如果你手动拼字典时用了
"Logging.LogLevel.Default"
(点号而非冒号),就查不到。

必须用英文冒号
:
分隔层级,不能用点、下划线或斜杠
数组支持有限:JSON 中
["a","b"]
会被转成
Array:0=a
Array:1=b
,但反向绑定到
List<string></string>
时可能失败,建议避免在自定义源中暴露数组结构
空值处理:字典中存
null
值会导致
ConfigurationBinder
绑定失败,应存空字符串
""
或跳过该 key

复杂嵌套或动态 schema 的场景,优先考虑用

IOptions<t></t>
+ 自定义 binder,而不是硬塞进 flat 字典。

相关推荐