在C#中设置树节点父节点的正确方法?

我正在开发一个自定义树。 每个节点(BindingNode是我如何调用它们)包含一个BindingNodeCollection,它实现ICollection并包含更多节点。 我的问题是,用户应该能够使用名为Parent的readonly属性访问每个节点的父节点,就像在TreeNode中一样 。 但是通过调用BindingNodeCollection的Add(BindingNode node)方法将节点添加到BindingNodeCollection。 BindingNodeCollection知道它自己的父是什么,但是,不能在Add(BindingNode node)方法中分配BindingNode的Parent,因为Parent应该是readonly。 我想要实现的function与TreeView中的TreeNode和TreeNodeCollection的function基本相同:

-TreeNode的Parent是readonly。

-TreeNodes通过调用TreeNodeCollection的Add(TreeNode node)方法分配给TreeNodeCollection。

-TreeNode的Parent给出TreeNode,其中包含添加了TreeNode的TreeNodeCollection。

-TreeNodeCollection未在TreeNode中定义,以便可以访问父私有字段。

这是我想念C ++的friend 。 🙁

有几种方法可以实现您所追求的目标,这实际上取决于您想要的安全性。 这是一个只有您或您的同事会触摸的图书馆或“封闭式”应用程序吗? 在使用它们之前,需要考虑以下一些建议和问题。

  1. 使BindingNode上的属性设置器为内部设置; 你相信大会中的每个人都不是孤儿吗?

  2. 将BindingNodeCollection公开为ReadOnly,并提供修改BindingNode本身集合的方法。 Add可以设置私有Parent属性。 需要删除才能将Parent属性设置为null。 这非常被锁定,污染你的基类节点值得安心吗?

  3. 接受透明度对您来说比安全性更重要,并将Parent setter公开为public。 你相信每个能看到你的课程而不是孤儿的人吗?

为了进一步阅读和更好的想法,你几乎描述的是复合模式 。 关于此模式的安全性与透明性之间存在大量讨论,其中大部分涉及公开这些类以供公众在某些API中使用。 对你的情况来说可能有点过头了,或者你可能正是你需要考虑的事情,我不知道你的问题是什么范围。

内部修饰符是C#等同于友元类,以使Parent的SET方法只能访问同一程序集中的类。

 TreeNode Parent { get; internal set;} 

我认为它被称为装饰模式? 如果我是对的,请来点。 我永远记不起模式的名字..

我创建了一个在add和构造中构造的类具有Parent属性集,并且只是将节点作为成员拥有。 如果有BindingNode的接口,那么我将实现具有所有方法和属性的接口传递给实际的BindingNode。

 public class BoundNode : INode { private INode _thisNode { get; private set; } public INode Parent { get; private set; } public BoundNode(INode bindingNode, INode parent) { _thisNode = bindingNode; Parent = parent; } // Implement pass throughs to the _thisNode member } 

然后add方法将实现

 public Add(INode someNode) { _nodeList.Add(new BoundNode(someNode, this.Parent)); } 

或类似的东西..但是你的collections知道它的节点上下文..

 public class BindingNode { private BindingNode _parent; private List _children = new List(); public IEnumerable Children { get { return _children; } } public BindingNode Parent { get { return _parent; } } public void AddChild( BindingNode node ) { node._parent = this; _children.Add( node ); } } 

正确的方法是将子节点分配给父节点。 像这样:

 parentTreeNode.Nodes.Add(childTreeNode);