C# ASP.NET中AppSettings.json加载后Dictionary顺序不符如何处理?
解决方案
问题原因
默认的Dictionary<TKey, TValue>类型本身不承诺保留元素的插入顺序,同时ASP.NET Core内置的配置绑定逻辑处理字典类型时,没有额外保留JSON配置中键值对声明顺序的处理,因此会出现加载后顺序和配置文件不一致的情况。
方案1:更换有序字典类型(改动最小)
适用.NET 7及以上版本
.NET 7开始官方新增了泛型有序字典System.Collections.Generic.OrderedDictionary<TKey, TValue>,绑定逻辑会自动保留JSON配置的顺序,直接修改配置模型即可:
using System.Collections.Generic; public class Configuration : IConfiguration { public string Separator { get; set; } public OrderedDictionary<string, string> CsvMapping { get; set; } }
适用.NET 6及更早版本
使用System.Collections.Specialized.OrderedDictionary非泛型有序字典:
using System.Collections.Specialized; public class Configuration : IConfiguration { public string Separator { get; set; } public OrderedDictionary CsvMapping { get; set; } }
取值时按需转换类型即可:var value = CsvMapping["Firstname"] as string;
方案2:手动绑定配置节点(不修改原有属性类型)
如果不想改动原有配置模型的属性类型,可以手动遍历配置节点按顺序赋值,GetChildren()返回的节点顺序和JSON配置的声明顺序完全一致:
// Program.cs 中注册配置时手动处理 var configNode = builder.Configuration.GetSection("Configuration"); var myConfig = new Configuration { Separator = configNode.GetValue<string>("Separator"), CsvMapping = new Dictionary<string, string>() }; foreach (var child in configNode.GetSection("CsvMapping").GetChildren()) { myConfig.CsvMapping.Add(child.Key, child.Value); } builder.Services.AddSingleton(myConfig);
注意:该方案依赖当前版本Dictionary插入无删除操作时暂时保留顺序的特性,若需要长期稳定保序,还是建议使用有序字典类型。
方案3:调整配置结构为数组(全版本兼容)
如果需要兼容所有.NET版本,也可以调整JSON配置结构,将键值对改为数组存储,天然保序:
修改AppSettings.json:
"Configuration": { "Separator": ";", "CsvMapping": [ { "Key": "Firstname", "Value": "firstname" }, { "Key": "Lastname", "Value": "lastname" }, { "Key": "State", "Value": "state" }, { "Key": "Info", "Value": "info" } ] }
修改配置模型:
public class Configuration : IConfiguration { public string Separator { get; set; } public List<KeyValuePair<string, string>> CsvMapping { get; set; } }
需要按key查询时,可随时调用CsvMapping.ToDictionary(x => x.Key, x => x.Value)转换为字典使用。
内容的提问来源于stack exchange,提问作者Felix Arnold
相关产品推荐
相关产品推荐

