我有一个对象,里面有多个嵌套对象。类:
public class Element
{
public string Key { get; set; }
public List<Element> SubElement { get; set; }
[XmlIgnore]
public ElementConfig ElementConfig { get; set; }
[XmlIgnore]
public Element ParentElement { get; set; }
}
public class SubElement
{
public string Key { get; set; }
public List<Element> Elements { get; set; }
}
[Serializable]
public class ElementConfig {
public string Key { get; set; }
public string Label { get; set; }
public string TypeName { get; set; }
public string IconName { get; set; }
}
其基础是,一个元素
可以有多个子元素
以及它们自己的ElementConfig
。我想为每个元素
填充ElementConfig
,如下所示:
private void Recursion(Element element)
{
//TODO: use recursion ??
foreach (Element item in element.SubElement)
{
item.ElementConfig = navigationStructureConfig.ElementConfigs.SingleOrDefault(x => x.Key == item.Key);
item.ParentElement = element;
foreach (Element x in item.SubElement)
{
x.ElementConfig = navigationStructureConfig.ElementConfigs.SingleOrDefault(e => e.Key == x.Key);
x.ParentElement = item;
foreach (Element y in x.SubElement)
{
y.ElementConfig = navigationStructureConfig.ElementConfigs.SingleOrDefault(e => e.Key == y.Key);
y.ParentElement = x;
}
}
}
}
这是起作用的,但我想用一个递归的方法来做这件事。这可能吗?
根据@johnathan Barclay的建议编辑我使用以下方法:
element.ElementConfig = navigationStructureConfig.ElementConfigs.SingleOrDefault(x => x.Key == element.Key);
foreach (var item in element.SubElement)
{
item.ParentElement = element;
Recursion(item);
}
这有助于获取每个第一个子元素
的ElementConfig
。现在发生的情况是以下子元素没有填充。
假设还需要为根元素设置elementconfig
:
private void Recursion(Element element)
{
element.ElementConfig = navigationStructureConfig.ElementConfigs
.SingleOrDefault(x => x.Key == element.Key);
foreach (var item in element.SubElement)
{
item.ParentElement = element;
Recursion(item); // Recurse here
}
}
下面是一个通用的迭代解决方案:
public void PupulateConfigAndParent(Element element){
foreach(var (item, parent) in DepthFirstWithParent(element, e => e.SubElement)){
item.ElementConfig = navigationStructureConfig.ElementConfigs.SingleOrDefault(x => x.Key == item.Key);
item.ParentElement = parent;
}
}
public static IEnumerable<(T Node, T Parent)> DepthFirstWithParent<T>(T self, Func<T, IEnumerable<T>> selector)
{
var stack = new Stack<(T Node, T Parent)>();
stack.Push((self, self));
while (stack.Count > 0)
{
var current = stack.Pop();
yield return current;
foreach (var child in selector(current.Node))
{
stack.Push((child, current.Node ));
}
}
}
这样做的一个优点是可以对任何类型的树状结构重用泛型方法。注意,根节点将自己作为父节点。