ASP.NET Core:如何将appsettings.json配置节读取为不可变记录
如何将appsettings.json配置节读取为带不可变集合的不可变记录?
问题场景
假设你的appsettings.json有如下配置:
{ "MySection": { "Id": 5, "Names": { "John": "Manager", "Sally": "Boss" } } }
需要将MySection转换为以下不可变记录类型:
public record MyConfig(int Id, ImmutableDictionary<string, string> Names);
直接使用Configure<T>会报错:
serviceCollection.Configure<MyConfig>(this.Configuration.GetSection("MySection"));
UnhandledException... ...Cannot dynamically create an instance of type 'MyConfig'. Reason: No parameterless constructor defined.
原因是默认配置绑定系统要求目标类型有公共无参构造函数,且属性支持设置,而不可变记录的主构造函数没有无参版本,同时不可变集合也无法被默认绑定系统处理。
简洁解决方案
方案1:使用Configuration.Get<T>直接获取(推荐)
在.NET 6及以上版本中,Configuration.GetSection().Get<T>()方法内部基于System.Text.Json实现,天然支持不可变记录和不可变集合(包括ImmutableDictionary)。
代码示例:
// 从配置节读取并反序列化为不可变记录实例 var myConfig = Configuration.GetSection("MySection").Get<MyConfig>(); // 将实例注册到依赖注入容器 serviceCollection.AddSingleton(myConfig);
如果需要通过IOptions<MyConfig>方式访问,可结合AddOptions注册:
serviceCollection.AddOptions<MyConfig>() .Configure<IConfiguration>((_, config) => { return config.GetSection("MySection").Get<MyConfig>(); });
注:若使用
IOptions,更推荐直接注册实例的方式,避免不必要的配置逻辑。
方案2:自定义配置绑定转换器(兼容旧版本)
如果你的项目基于.NET 5或更早版本,可自定义配置绑定的转换器来处理不可变集合和记录:
public static class ConfigurationExtensions { public static T GetImmutable<T>(this IConfiguration configuration) { var json = JsonSerializer.Serialize(configuration.AsEnumerable()); return JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions { Converters = { new JsonImmutableDictionaryConverter<string, string>() } }); } } // 使用方式 var myConfig = Configuration.GetSection("MySection").GetImmutable<MyConfig>(); serviceCollection.AddSingleton(myConfig);
关于“读取配置节为JSON字符串”的实现
如果确实需要将配置节转为JSON字符串,可通过以下方式实现:
var configDict = Configuration.GetSection("MySection") .AsEnumerable() .Where(kv => !string.IsNullOrEmpty(kv.Value)) .ToDictionary(kv => kv.Key, kv => kv.Value); var json = JsonSerializer.Serialize(configDict);
但此方法较为迂回,仅在特殊场景下使用。
内容的提问来源于stack exchange,提问作者MLavrentyev
相关产品推荐
相关产品推荐

