绑定 .NET Core 无法识别的配置属性
Posted
技术标签:
【中文标题】绑定 .NET Core 无法识别的配置属性【英文标题】:Binding .NET Core Unrecognized configuration properties 【发布时间】:2022-01-15 13:53:42 【问题描述】:假设我们有以下配置文件
"TeamRoster:People:0:Name": "Bryan",
"TeamRoster:People:0:City": "Toronto",
"TeamRoster:People:0:Interests": "Code",
"TeamRoster:People:1:Name": "Sebastian",
"TeamRoster:People:1:City": "Vancouver",
"TeamRoster:People:1:ApartmentType": "Condo"
以及代表此配置的以下 POCO:
public class TeamRoster
public Person[] People get; set;
public class Person
public string Name get; set;
public string City get; set;
假设我使用 ConfigurationBuilder 来读取 dotnet 核心配置,例如:
IConfiguration config =
new ConfigurationBuilder()
.AddJsonFile("file.json")
.Build();
var myConfig = config.GetSection("TeamRoster").Get<TeamRoster>();
如何捕获不属于 Person 对象的其他属性(Interests、ApartmentType)?
我的推理超出了上面的琐碎示例。在我的模型中,我可能有几十个附加属性(例如多态类型),我想捕获它们而不必在配置对象中定义它们。理想情况下,我想像[JsonExtendedData] 那样做,但据我所知,即使数据表示为 Json,这只是源。它被读入一个配置对象,然后绑定。
有没有办法自定义 .net 核心绑定?
【问题讨论】:
如果您不知道要创建什么以及有多少,您将如何为其他属性创建一个类。 我想要一个无法识别属性的字典,就像 JsonExtendedData 一样。 好的,你认为这本词典的关键是什么?只是 name ,还是整个字符串? 不确定我明白你在问什么@Serge。基本上,基础配置中未映射到对象属性的任何无法识别的属性都应被视为“无法识别”。所以关键是属性的名称。 【参考方案1】:为了阐明这一点,Microsoft.Extensions.Configuration 中的IConfigurationRoot
从其底层配置源中抽象出配置数据。开箱即用的配置数据可以来自Json、Azure KeyVault、Command Line、Environment Variables、Xml、Memory、Ini files、User secrets 和individual files(每个文件的密钥) .
这些配置源中的每一个都将其数据加载到字典中,其中层次值使用“:”分隔。当您从 IConfiguration
对象中获取数据时,它会尝试以相反的顺序解析来自每个数据源的值。因此最后添加的配置源具有最高优先级。
IConfiguration
对象到 POCO 对象的映射是使用 ConfigurationBinder 完成的。虽然ConfigurationBinder
确实支持使用TypeConverters 解析值,但这种情况仅有助于映射配置字典中的单个字符串值,而不是整个对象。
ConfigurationBinder
原生支持绑定集合,所以理论上以下两种方法可以用于以下配置。
将固定值与动态值分开
表示数据,使动态数据与静态数据分开。
"auth":
"providers": [
"name": "clientsecret",
"loginUrl": "https://login.microsoftonline.com/mytenant/oauth2",
"fields":
"client_id": "xxx",
"client_secret": "yyy"
"resource": "https://management.azure.com",
"grant_type": "client_credentials"
,
...
]
将动态字段绑定到Dictionary<string,string>
时,Binder 将字段映射为键/值对。这种方法的主要优势是我们能够利用 TypeConverters 和固定字段的类型安全性。
public class AuthProvider
// FIXED FIELDS
public string Name get; set;
public Uri LoginUrl get; set;
// DYNAMIC FIELDS
public Dictionary<string,string> Fields get; set;
将所有数据映射为动态
稍微有点hackish的方法是将数据中的所有字段描述为兄弟,然后将整个数据绑定为字典。
"auth":
"providers": [
"name": "clientsecret",
"loginurl": "https://somewhere",
"client_id": "xxx",
"client_secret": "yyy",
"scope": "https://url",
"grant_type": "client_credentials"
]
我们可以简单地利用直接绑定到字典的优势。请注意,我们使用了 Uri 字段的类型转换器:
public class AuthProvider : Dictionary<string,string>
public string Name => this["name"]
public string LoginUrl => this["loginUrl"]
public Dictionary<string,string> Fields
get
var propertyNames = GetType().GetProperties().Select(x => x.Name).ToArray();
var keyPairs = this.Where(kvp => !propertyNames.Contains(kvp.Key));
return
new Dictionary<string,string>(
keyPairs,
StringComparer.OrdinalIgnoreCase);
【讨论】:
以上是关于绑定 .NET Core 无法识别的配置属性的主要内容,如果未能解决你的问题,请参考以下文章
.NET Core 重定向中无法识别的参数类型 REMOTE_ADDR 和 HTTP_X_FORWARDED_FOR
不同 Windows 上无法识别的属性“multipleSiteBindingsEnabled”问题
分析器错误消息: 无法识别的属性“targetFramework”。
Subsonic 2.2 ASP.NET MVC 无法识别的配置部分
无法识别的属性 requestValidationMode 请注意属性区分大小写 这是怎么回事
BScompilation debug=true targetFramework=4.0 无法识别的属性“targetFramework”