Как я могу обнаружить добавления в общий список в C # 4.0? - PullRequest
8 голосов
/ 07 июля 2011

У меня есть подкласс List<Location>, называемый LocationList. Для нас это удобный способ добавить другие свойства (например, IsExpanded и такие, которые мы можем использовать в пользовательском интерфейсе. Достаточно хорошо. Но теперь мы хотим, чтобы каждое местоположение знало о своем родителе. Таким образом, мы должны быть уведомляется, когда что-то добавляется в LocationList, но вы не можете переопределить Add и Remove. Хотя мы можем использовать ObservableCollection, это скорее конструкция View / ViewModel. Это чистые данные модели.

Конечно, мы могли бы вручную установить родительский элемент при добавлении его в коллекцию, но я ненавижу неавтоматизированную логику, подобную этой, поскольку нет ничего, чтобы правильно установить его набор. Позвольте коллекции (ну, List) автоматически сказать: «Эй ... вы добавлены, поэтому я назначу вашему родителю класс, который владеет мной». Вот что я хочу.

Моя мысль состоит в том, чтобы вместо подкласса List<Location> вместо этого просто создать прямой класс, который использует List<Location> внутри, и тогда я могу просто выставить свои собственные методы Add / Remove и обработать корректировки для 'Parent' там. , Однако это нарушает возможность перечисления по внутренней коллекции, поскольку она внутри.

Тем не менее, есть ли способ прослушать изменения List<Location> или, по крайней мере, делегировать его интерфейс IEnumerable от обернутого объекта его оболочке?

Ответы [ 6 ]

9 голосов
/ 07 июля 2011

Измените LocationList, чтобы он наследовал от Collection<Location>.Я не знаю, почему List<T> не запечатан, но его нельзя расширять.

Источник: Руководство по разработке инфраструктуры, второе издание, стр. 251:

List<T> - этооптимизирован для производительности и мощности за счет чистоты API и гибкости.

4 голосов
/ 07 июля 2011

List<T> имеет защищенных членов InsertItem<T>, RemoveItem<T> и т. Д., Которые вы можете переопределить в своем производном классе, чтобы делать то, что вы хотите.

** ОБНОВЛЕНИЕ **

На самом деле вышеприведенное неверно, Collection<T> имеет эти защищенные методы. Как правило, при получении пользовательских классов List рекомендуется использовать Collection<T>, а не List<T>.

См. этот ответ .

2 голосов
/ 07 июля 2011

Моя мысль состоит в том, чтобы вместо подкласса List вместо этого просто создать прямой класс, который использует List для внутреннего использования, а затем я могу просто представить свои собственные методы Add / Remove и обработать корректировки для 'Parent' там.Однако это нарушает возможность перечисления внутренней коллекции, поскольку она находится внутри.

Вы все еще можете реализовать IEnumerable<Location> в своей пользовательской коллекции.Используйте List<> в качестве внутренней детализации класса, и вы можете разрешить перечисление через интерфейс.

class LocationList : IEnumerable<Location>
{
    List<Location> _list; // initialize somewhere

    public IEnumerator<Location> GetEnumerator() 
    {
         return _list.GetEnumerator();
    }

    IEnumerable.IEnumerator GetEnumerator() 
    {
         return this.GetEnumerator();
    }

    // ... your other custom properties and methods
}
1 голос
/ 07 июля 2011

Попробуйте универсальный BindingList<T>, который вызывает события, когда элементы добавляются и удаляются.

0 голосов
/ 07 июля 2011

Вы можете использовать Шаблон наблюдателя

0 голосов
/ 07 июля 2011

Однако это нарушает возможность перечисления по внутренней коллекции, поскольку она находится внутри.

Это неверно, если вы следуете правильной технике и реализуете IEnumerable и ICollection

Но я бы использовал коллекцию Observable вместо того, чтобы заново изобретать колесо.

И, конечно, вы можете использовать Реактивные расширения , чтобы делать то, что вам нужно.

...