有没有办法将对象(或引用)传递给函数,当该对象处于'构造之下时?在递归?我想把我的父节点放在他的孩子身上。
以某种方式打电话:
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();
}
答案 0 :(得分: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();
答案 1 :(得分: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完全编写。我会把它作为一种练习留给你。