gpt4 book ai didi

c# - 将 netcore IConfigurationSection 绑定(bind)到动态对象

转载 作者:行者123 更新时间:2023-11-30 17:30:22 25 4
gpt4 key购买 nike

在我的 appSettings.json 中,我有一个配置部分,只要它是 json 有效的,它就可以包含任何内容。它通常是一组键/值(字符串/字符串)

我想在我的代码中获取它并在 Controller 调用中返回它。

我查看了源代码 ( https://github.com/aspnet/Configuration/blob/6d9519622b5db2c5ac6bafa8bcdb25fe27914de3/src/Config.Binder/ConfigurationBinder.cs ),似乎我注定要使用现成的解决方案。

如果我将用例限制为键值对,我可以在 IConfigSection 中使用 AsEnumerable(),这很好。如果我想允许列表,那么我可能仍然可以解析 key 以查找 :Number 但是有人有办法轻松反序列化随机对象吗?或者甚至更好地获取配置部分而不对其进行反序列化。

例如

{
"mySettings":
{
"key1": "value1",
"key2": "value2",
"list": [ "item1", "item2", "item3" ],
"complexObject": {
"key": "value",
"anything" : [{"id": "3", "name": "John"}]
}
}
}

最佳答案

如果您滥用 .NET 4 动态对象,则有可能。正如您所说,您可以枚举配置中的所有键,它们都遵循相同的模式。对于您的示例,所有感兴趣的键都是:

mySettings null 
mySettings:list null
mySettings:list:2 item3
mySettings:list:1 item2
mySettings:list:0 item1
mySettings:key3 value3
mySettings:key2 value2
mySettings:key1 value1
mySettings:complexObject null
mySettings:complexObject:key value
mySettings:complexObject:anything null
mySettings:complexObject:anything:0 null
mySettings:complexObject:anything:0:name John
mySettings:complexObject:anything:0:id 3

由此,我们可以构建一个 ExpandoObject,如下所示:

[HttpGet]
public IActionResult Get([FromServices] IConfiguration config)
{
var result = new ExpandoObject();

// retrieve all keys from your settings
var configs = config.AsEnumerable().Where(_ => _.Key.StartsWith("mySettings"));
foreach(var kvp in configs)
{
var parent = result as IDictionary<string, object>;
var path = kvp.Key.Split(':');

// create or retrieve the hierarchy (keep last path item for later)
var i = 0;
for (i = 0; i < path.Length - 1; i++)
{
if (!parent.ContainsKey(path[i]))
{
parent.Add(path[i], new ExpandoObject());
}

parent = parent[path[i]] as IDictionary<string, object>;
}

if (kvp.Value == null)
continue;

// add the value to the parent
// note: in case of an array, key will be an integer and will be dealt with later
var key = path[i];
parent.Add(key, kvp.Value);
}

// at this stage, all arrays are seen as dictionaries with integer keys
ReplaceWithArray(null, null, result);

return Ok(result);
}

private void ReplaceWithArray(ExpandoObject parent, string key, ExpandoObject input)
{
if (input == null)
return;

var dict = input as IDictionary<string, object>;
var keys = dict.Keys.ToArray();

// it's an array if all keys are integers
if (keys.All(k => int.TryParse(k, out var dummy))) {
var array = new object[keys.Length];
foreach(var kvp in dict) {
array[int.Parse(kvp.Key)] = kvp.Value;
// Edit: If structure is nested deeper we need this next line
ReplaceWithArray(input, kvp.Key, kvp.Value as ExpandoObject);
}

var parentDict = parent as IDictionary<string, object>;
parentDict.Remove(key);
parentDict.Add(key, array);
}
else
{
foreach (var childKey in dict.Keys.ToList())
{
ReplaceWithArray(input, childKey, dict[childKey] as ExpandoObject);
}
}
}

注意:由于冒号 : 用作分隔符,因此您不能拥有包含冒号的键。

最后,因为你现在有了一个动态对象,你可以直接获取它的属性:

dynamic asDym = result;
string name = asDym.mySettings.complexObject.anything[0].name;

关于c# - 将 netcore IConfigurationSection 绑定(bind)到动态对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50007146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com