Реализация дерева в c #, управляющего parent-child - PullRequest
3 голосов
/ 13 января 2009

Я реализую дерево, думаю о нем как о структуре папок, поэтому у меня есть класс, который выглядит следующим образом:

public class Folder
{
    //Various Props like Name etc.
    public IList<Folder> Children{get;}
    public Folder Parent {get;}
}

Теперь я хочу идти вверх и вниз по дереву, чтобы по корню я мог найти лист, а по листу я мог найти корневой узел. Поэтому каждому ребенку нужен родитель. Теперь вопрос в том, как лучше всего добавить новый узел в дерево. Я использовал два решения в прошлом:

  1. Добавить метод AddChild (Folder) в папку, который обрабатывает добавление папки и может установить родительский элемент. Проблема в том, что теперь мне нужно заблокировать мою коллекцию Children, чтобы вы не могли обойти этот метод.
  2. Создайте мою собственную коллекцию Children, которой будет возвращена ссылка на экземпляр, чтобы он мог обрабатывать установку родительского элемента в надстройке. Проблема с этим, я должен реализовать новую коллекцию.
  3. Использовать коллекцию, в которой есть события, когда элементы добавляются или удаляются.

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

Ответы [ 5 ]

3 голосов
/ 13 января 2009

После просмотра на MSDN вы можете попробовать это:

List<Folder> children;

public ReadOnlyCollection<Folder> Children
{
    get { return this.children.AsReadOnly(); }
}

Если ваш личный участник должен быть объявлен как IList, мы можем скопировать его в список и затем вернуть. Но я действительно не вижу проблемы с использованием конкретной реализации в качестве частного участника. Изменение реализации позже не нарушит совместимость.

IList<Folder> children;

public ReadOnlyCollection<Folder> Children
{
    get 
    { 
        return new List<Folder>(this.children).AsReadOnly(); 
    }
}
1 голос
/ 13 января 2009

Внедрение собственной коллекции - большая работа; реализация оболочки для существующего класса коллекции, который предоставляет только два или три метода, не является. И, похоже, это то, что вы ищете, судя по вашему ответу на JayArr. Что-то вроде:

public class ChildCollection
{
   // _Children is maintained by the Folder class, hence the internal access specifier
   internal Dictionary<KeyType, Folder> _Children = new Dictionary<KeyType, Folder>;

   public this[KeyType key]
   {
      get
      {
          return _Children[key];
      }
   }

   public IEnumerable<KeyType> Keys
   {
      get
      {
         return _Children.Keys;
      }
   }
}
1 голос
/ 13 января 2009

Я бы выбрал вариант 1, а затем сделал бы свойство Children таким:

    public IEnumerable<Folder> Children
    {
        get { return this.children.GetEnumerator(); }
    }

Теперь необходимо добавить AddChild, чтобы добавить потомков. Коллекция недоступна.

1 голос
/ 13 января 2009

Идите с номером 1, но сделайте свой свойство Children IEnumerable таким образом, чтобы пользователи не могли добавить его в коллекцию.

1 голос
/ 13 января 2009

Лично я бы пошел с методом 1. Разрешение клиентскому коду манипулировать коллекцией Children в любом случае напрямую нарушает инкапсуляцию, поэтому «блокировка» коллекции Children - это правильная вещь & trade;.

«Правильная» стратегия поддержания правильных отношений между узлами зависит от потребностей ваших клиентов. Я предполагаю, что в этой конкретной ситуации вы бы хотели, чтобы клиенты могли сами изменять дочерние узлы, но не коллекцию Children. Если это так, я думаю, что предложение Роба Пруза (сделать свойство Children возвращаемым IEnumerable), вероятно, является лучшим выбором. В других ситуациях, ReadOnlyCollection, вероятно, будет лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...