ОП! :) Спасибо за попытку, хотя. Просто жаль, что нет области «Друг», как в C ++, но похоже, что по большей части частного интерфейса будет достаточно. Еще раз спасибо!

здаем иерархию объектов, где каждый элемент имеет коллекцию других элементов, и каждый элемент также имеетParent свойство, указывающее на его родительский элемент. Довольно стандартные вещи. У нас также естьItemsCollection класс, который наследуется отCollection<Item> который сам по себе имеетOwner свойство, указывающее на элемент, которому принадлежит коллекция. Опять ничего интересного там нет.

Когда элемент добавляется вItemsCollection класс, мы хотим, чтобы он автоматически установил родителя Item (используя коллекциюOwner свойство) и когда элемент удаляется, мы хотим очистить родительский элемент.

Вот вещь Мы хотим толькоParent сеттер будет доступен дляItemsCollection, ничего больше. Таким образом, мы можем не только узнать, кто является родителем элемента, но мы также можем убедиться, что элемент не добавлен в несколько коллекций, проверив существующее значение вParentили позволить кому-то произвольно изменить его на что-то другое.

Мы знаем, как это сделать двумя способами:

Отметьте сеттер как частный, а затем заключите определение коллекции в область самого элемента. Pro: Полная защита. Con: Гадкий код с вложенными классами.

Используйте личноеISetParent интерфейс на элементе, который толькоItemsCollection знает о. Pro: намного чище код и легко следовать. Con: Технически любой, кто знает об интерфейсе, может разыграть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();
    }

}

Любой другой способ сделать что-то подобное?

Ответы на вопрос(9)

Ваш ответ на вопрос