2016-08-26 104 views
1

当递归中的对象处于'构造'下时,是否有任何方法将对象(或引用)传递给函数?我想把我的父节点放在他的孩子身上。在递归中传递父节点

调用发生在一些方法:

NavigationTreeNode node = FindNode(Resources.ShellView_TreeNodeBusinessRules); 
var tmpList = LoadNodes(xDoc.Descendants("root").Elements("tab"), node); 

这是递归:

private List<NavigationTreeNode> LoadNodes(IEnumerable<XElement> nodes, NavigationTreeNode parentNode) 
{ 
    return nodes.Select(x => 
     new NavigationTreeNode(x.Attribute("display-name").Value, parentNode) 
     { 
      TabName = x.Attribute("tab-name").Value, 
      // Here I want to send object that is now under 
      // construction, or maybe reference 
      ChildNodes = LoadNodes(x.Elements("tab"), /* ?? */) 
     }).ToList(); 
} 

回答

2

您可以添加{}指定lambda表达式的范围,然后你可以保存你的新对象设置其属性,然后返回它:

return nodes.Select(x => 
{ 
    var obj = new NavigationTreeNode(x.Attribute("display-name").Value, parentNode) 
    { 
     TabName = x.Attribute("tab-name").Value 
    }; 
    obj.ChildNodes = LoadNodes(x.Elements("tab"), obj); 
    return obj; 
}).ToList(); 
+0

令人惊叹的人,它的工作原理!绝对需要LINQ更多的锻炼。仅供参考,是的,这只是简单的字符串。 –

+0

@p__d - 请告诉我现在这个编辑对你来说是否仍然正确 –

+0

什么时候会使递归失效? –

0

坦率地说,如果重新设计了导航类,这可以做得更好。对于这种特殊情况,该结构不适合使用linq来递归地重建它。虽然linq 可以使用来初始化递归结构,但当结构是双重链接时,它不能被有效利用。

而且一般来说,创建初始化结构时要使用的子项列表是错误的。当你提供对内部结构的直接访问时,它打破封装。无论如何,你应该提供操纵这些方法的方法。

举例来说,像这样的结构,它会使事情更容易:

class NavigationTreeNode 
{ 
    private List<NavigationTreeNode> childNodes = new List<NavigationTreeNode>(); 
    public NavigationTreeNode(string tabName, string displayName) 
    { 
     TabName = tabName; 
     DisplayName = displayName; 
    } 
    public NavigationTreeNode Parent { get; private set; } 
    public string TabName { get; } 
    public string DisplayName { get; } 
    public IReadOnlyList<NavigationTreeNode> ChildNodes => childNodes.AsReadOnly(); 

    public void Add(NavigationTreeNode childNode) 
    { 
     if (childNode.Parent != null) 
      childNode.Parent.Remove(childNode); 
     childNodes.Add(childNode); 
     childNode.Parent = this; 
    } 

    private void Remove(NavigationTreeNode childNode) 
    { 
     childNodes.Remove(childNode); 
     childNode.Parent = null; 
    } 
} 

然后负载的功能是这样的:

private NavigationTreeNode LoadNode(XElement node) 
{ 
    var treeNode = new NavigationTreeNode((string)node.Attribute("tab-name"), (string)node.Attribute("display-name")); 
    foreach (var tab in node.Elements("tab")) 
     treeNode.Add(LoadNode(tab)); 
    return treeNode; 
} 

,并根据你想多远去设计,你可以完全删除循环的需要,并使用linq完全写入。我将为你做这个练习。