2010-03-05 3 views
3

Я хотел бы создать IList<Child>, который постоянно сохраняет свои объекты Child в порядке/неявном порядке сортировки (т. Е. Вне зависимости от добавлений/абзацев в базовый список).IList с неявным порядком сортировки

То, что я специально пытаюсь избежать, - это необходимость для всех потребителей указанных IList<Child> явно ссылаться на IEnumerable<T>.OrderBy() каждый раз, когда они хотят его перечислить. Помимо нарушения DRY, такой подход также нарушит инкапсуляцию, так как потребители должны были бы знать, что мой список даже отсортирован, что на самом деле не является их бизнесом :)

Решение, которое показалось наиболее логичным/эффективным, заключалось в том, чтобы разоблачить IList<Child> как IEnumerable<Child> (для предотвращения мута List) и добавить явные методы добавления/удаления в содержащий Parent. Таким образом, я могу перехватить изменения в список, которые требуют повторного рода, и применить один с помощью Linq:

public class Child { 
    public string StringProperty; 
    public int IntProperty; 
} 

public class Parent{ 
private IList<Child> _children = new List<Child>(); 

     public IEnumerable<Child> Children{ 
     get 
     { 

      return _children; 
     } 
     } 
     private void ReSortChildren(){ 
     _children = new List<Child>(child.OrderBy(c=>c.StringProperty)); 
     } 
     public void AddChild(Child c){ 
      _children.Add(); 
      ReSortChildren() 
     } 
     public void RemoveChild(Child c){ 
      _children.Remove(c); 
      ReSortChildren() 
     } 
} 

Тем не менее, этот подход не перехватывают изменения, внесенные в базовых Child.StringProperty (который в данном случае является собственность, управляющая сортировкой). Должно быть более элегантное решение такой основной проблемы, но я не смог ее найти.

EDIT: Я не был уверен, что предпочтительнее LINQ-совместимое решение. Я бы предпочел не прибегать к использованию конструкций .NET 2.0 (т. Е. SortedList)

ответ

0

Один из способов, которым вы могли бы пойти, состоит в том, чтобы иметь Child опубликовать событие OnStringPropertyChanged, которое проходит по предыдущему значению StringProperty. Затем создайте вывод SortedList, который переопределяет метод Add для подключения обработчика к этому событию. Всякий раз, когда событие срабатывает, удалите элемент из списка и повторно добавьте его с новым значением StringProperty. Если вы не можете изменить Child, тогда я бы сделал прокси-класс, который либо происходит, либо обертывает Child для реализации события.

Если вы не хотите этого делать, я бы по-прежнему использовал SortedList, но внутренне управляю вышеуказанной логикой сортировки в любое время, когда необходимо изменить StringProperty. Чтобы быть сухим, желательно перенаправить все обновления на StringProperty с помощью общего метода, который правильно управляет сортировкой, а не для доступа к списку непосредственно из разных мест в классе и дублирования логики управления сортировкой.

Я также предостерег бы от того, чтобы контроллер передал ссылку на Child, что позволяет ему манипулировать StringProperty после его добавления в список.

public class Parent{ 
    private SortedList<string, Child> _children = new SortedList<string, Child>(); 

    public ReadOnlyCollection<Child> Children{ 
    get { return new ReadOnlyCollection<Child>(_children.Values); } 
    } 

    public void AddChild(string stringProperty, int data, Salamandar sal){ 
    _children.Add(stringProperty, new Child(stringProperty, data, sal)); 
    } 

    public void RemoveChild(string stringProperty){ 
    _children.Remove(stringProperty); 
    } 

    private void UpdateChildStringProperty(Child c, string newStringProperty) { 
    if (c == null) throw new ArgumentNullException("c"); 

    RemoveChild(c); 
    c.StringProperty = newStringProperty; 
    AddChild(c); 
    } 

    public void CheckSalamandar(string s) { 
    if (_children.ContainsKey(s)) 
     var c = _children[s]; 
     if (c.Salamandar.IsActive) { 
     // update StringProperty through our method 
     UpdateChildStringProperty(c, c.StringProperty.Reverse()); 
     // update other properties directly 
     c.Number++; 
    } 
    } 
} 
1

Как насчет использования SortedList<>?

+1

Это не работает.Если вы измените значение ключа в базовом объекте, порядок сортировки не изменится. –

0

I думаю что если вы получаете от KeyedCollection, вы получите то, что вам нужно. Тем не менее, это зависит только от чтения документации.

EDIT:

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

Смежные вопросы