C#:使用深层字符串表达式递归获取Dictionary值



我想使用字符串表达式作为键从Dictionary<string, object>中获取对象
例如以下数据结构:

var data = new Dictionary<string, object>()
{
{ "Products", new object[]
{
new Dictionary<string, object>()
{
{ "Name", "Tin of biscuits"  }
}
}
}
}

我想返回带有表达式"Products[0].Name"的产品名称
这只是一个例子,数据可以是任何深度,字符串表达式可以是类似于的"BookStore.Books[3].Author.ContactDetails.Address"

到目前为止,我一直在尝试递归方法,也尝试过string.Split('.')AggregateLinq方法,但我很挣扎,我认为这对So来说是一个完美的小谜题

假设数据结构中总是有Dictionary<string, object>object[],那么这种方法应该有效:

private static object? GetSelectedValueOrDefault(this Dictionary<string, object> data, string selector)
{
string[] selectorSegments = selector.Split('.');
if (selectorSegments.Length == 0)
{
return null;
}
object? currentNode = data.GetValueOrDefault(selectorSegments[0]);
if (currentNode == null)
{
return null;
}
for (int index = 1; index < selectorSegments.Length; index++)
{
string segment = selectorSegments[index];
if (currentNode is not Dictionary<string, object> dictionary)
{
return null;
}
var selectorWithIndex = GetSelectorAndElementIndexOrDefault(segment);
if (selectorWithIndex is not null &&
currentNode is Dictionary<string, object> dict)
{
currentNode = dict.GetValueOrDefault(selectorWithIndex.Value.ItemSelector);
currentNode = GetElementOrDefault(currentNode, selectorWithIndex.Value.Index);
continue;
}
currentNode = dictionary.GetValueOrDefault(segment);
if (index == selectorSegments.Length - 1)
{
return currentNode;
}
}
return null;
}
private static object? GetElementOrDefault(object? currentNode, int index)
{
if (currentNode is not object[] array)
{
return null;
}
if (index >= array.Length)
{
return null;
}
return array[index];
}
private static (string ItemSelector, int Index)? GetSelectorAndElementIndexOrDefault(string segment)
{
if (!segment.Contains('['))
{
return null;
}
string[] result = segment.Split('[', ']');
return (result[0], int.Parse(result[1]));
}

示例

var data = new Dictionary<string, object>()
{
{
"BookStore",
new Dictionary<string, object>()
{
{
"Name",
"The Book Store"
},
{
"Books",
new object[]
{
new Dictionary<string, object>(),
new Dictionary<string, object>(),
new Dictionary<string, object>(),
new Dictionary<string, object>()
{
{
"Author",
new Dictionary<string, object>()
{
{
"Name",
"Luke T O'Brien"
},
{
"ContactDetails",
new Dictionary<string, object>()
{
{
"Address",
"Some address"
}
}
}
}
}
}
}
}
}
}
};
Console.WriteLine(data.GetSelectedValueOrDefault("BookStore.Name"));
Console.WriteLine(data.GetSelectedValueOrDefault("BookStore.Books[3].Author.Name"));
Console.WriteLine(data.GetSelectedValueOrDefault("BookStore.Books[3].Author.ContactDetails.Address"));

输出

The Book Store
Luke T O'Brien
Some address

最新更新