【发布时间】:2011-09-30 14:43:54
【问题描述】:
我们正在创建一个对象层次结构,其中每个项目都有其他项目的集合,每个项目还有一个指向其父项目的Parent 属性。很标准的东西。我们还有一个ItemsCollection 类,它继承自Collection<Item>,它本身有一个Owner 属性指向集合所属的项目。同样,那里没有什么有趣的。
当一个项目被添加到ItemsCollection 类时,我们希望它自动设置项目的父项(使用集合的Owner 属性),当项目被删除时,我们希望清除父项。
事情就是这样。我们只希望Parent 设置器可用于ItemsCollection,仅此而已。这样,我们不仅可以知道项目的父项是谁,而且我们还可以通过检查 Parent 中的现有值或让某人随意将其更改为其他值来确保不会将项目添加到多个集合中。
我们知道如何做到这一点的两种方法是:
将 setter 标记为私有,然后将集合定义包含在项目本身的范围内。优点:全面保护。缺点:带有嵌套类的丑陋代码。
在只有
ItemsCollection知道的Item 上使用私有ISetParent接口。优点:代码更简洁,易于理解。缺点:从技术上讲,任何了解该界面的人都可以使用Item并获得二传手。
现在从技术上讲,任何人都可以通过反射获得任何东西,但仍然......试图找到最好的方法来做到这一点。
现在我知道 C++ 中有一个名为 Friend 的功能,或者可以让您将一个类中的其他私有成员指定为可供另一个类使用的功能,这将是完美的场景,但我不知道有任何此类C# 中的东西。
在伪代码中(例如,为简洁起见,所有属性更改通知等已被删除,我只是在这里输入,而不是从代码中复制),我们有这个...
public class Item
{
public string Name{ get; set; }
public Item Parent{ get; private set; }
public ItemsCollection ChildItems;
public Item()
{
this.ChildItems = new ItemsCollection (this);
}
}
public class ItemsCollection : ObservableCollection<Item>
{
public ItemsCollection(Item owner)
{
this.Owner = owner;
}
public Item Owner{ get; private set; }
private CheckParent(Item item)
{
if(item.Parent != null) throw new Exception("Item already belongs to another ItemsCollection");
item.Parent = this.Owner; // <-- This is where we need to access the private Parent setter
}
protected override void InsertItem(int index, Item item)
{
CheckParent(item);
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
this[index].Parent = null;
base.RemoveItem(index);
}
protected override void SetItem(int index, Item item)
{
var existingItem = this[index];
if(item == existingItem) return;
CheckParent(item);
existingItem.Parent = null;
base.SetItem(index, item);
}
protected override void ClearItems()
{
foreach(var item in this) item.Parent = null; <-- ...as is this
base.ClearItems();
}
}
还有其他类似的方法吗?
【问题讨论】:
标签: c# parent-child private friend