Я хочу создать настраиваемую наблюдаемую коллекцию (может быть связана с XAML), но я хочу отслеживать дополнительную информацию, которая требует переопределения наблюдаемых методов сбора. Методы ObservableCollection не являются виртуальными , но это означает, что единственный способ «переопределить» их - это просто скрыть их с помощью ключевого слова «new».Вот простой пример того, что я имею в виду:
//Tracks how many objects of each type are in this collection
class CustomCollectionInherited:ObservableCollection<Object>
{
private Dictionary<Type, UInt32> _count = new Dictionary<Type,uint>();
public UInt32 getTypeCount(Type T)
{
return _count[T];
}
#region Base Method 'Overrides'
new public void Add(Object item)
{
base.Add(item);
if (!_count.ContainsKey(item.GetType())) {
_count[item.GetType()] = 1;
} else {
_count[item.GetType()] += 1;
}
}
new public bool Remove(Object item)
{
if (base.Remove(item))
{
_count[item.GetType()] -= 1;
return true;
}
return false;
}
#endregion
}
У меня есть две проблемы с этим.Во-первых, хотя существует много методов, которые я хочу наследовать от ObservableCollection, таких как перечислители, интерфейс INotifyCollectionChanged и т. Д., есть много методов, которые я не хочу наследовать .А именно, методы, которые изменяют коллекцию, такие как Clear (), ClearItems (), Insert (), InsertItem () и еще 13, которые приводят к тому, что счетчик типов моей коллекции не синхронизируется.Похоже, это аргумент для композиции.
Вторая проблема - upcasting - программист может случайно обойти мои пользовательские реализации, используя мою коллекцию таким образом, что она будет передана наунаследованный тип.Например:
myCustomObj.AddToCollection( myCustomCollectionInherited );
...
void CustomObj.AddToCollection( Collection c )
{
c.Add(this);
}
Это довольно надуманный пример, но в таком случае будет использоваться унаследованный метод «Добавить», и счетчик типов моей коллекции снова выйдет из синхронизации.Кажется, что нет никакого способа обойти это, если моя коллекция не отслеживает событие base.CollectionChanged и каждый раз перестраивает счет с нуля, что полностью отрицает цель поддержания счета за O (1).
Исходя из этих проблем, я начал думать, что подходящим решением является создание класса, который содержит ObservableCollection.Но помните, мне нужно это для привязки к XAML как наблюдаемой коллекции, поэтому я должен реализовать все соответствующие интерфейсы, которые реализует ObservableCollection, чтобы он мог быть привязан к пользовательскому интерфейсу таким же образом.Ниже приведен пример:
//Tracks how many objects of each type are in this collection
class CustomCollectionEncapsulated : IList<object>, INotifyCollectionChanged
{
private ObservableCollection<Object> _base = new ObservableCollection<object>();
private Dictionary<Type, UInt32> _count = new Dictionary<Type, uint>();
public UInt32 getTypeCount(Type T)
{
return _count[T];
}
public void Add(object item)
{
_base.Add(item);
if (!_count.ContainsKey(item.GetType())) {
_count[item.GetType()] = 1;
} else {
_count[item.GetType()] += 1;
}
}
public bool Remove(object item)
{
if (_base.Remove(item))
{
_count[item.GetType()] -= 1;
return true;
}
return false;
}
}
Конечно, вышеупомянутое само по себе не компилируется, потому что IList реализует ICollection, IEnumerable, IEnumerable, каждый из которых имеет методы, которые мне нужно реализовать, и так далее, пока яв итоге получается около 20 дополнительных методов и сотни строк кода, каждый из которых говорит:
Type methodINeedToImplement(Params)
{
return _base.methodINeedToImplement(Params);
}
или
Type methodINeedToImplement(Params)
{
throw new NotImplementedException();
}
Основная причина наследования заключается в том, что программисту не нужновыполнить всю эту работу для 95% методов и событий, которые они не меняют.
Так что мне делать?Я абсолютно не могу убедить своего босса, что лучший способ защитить эту пользовательскую коллекцию - использовать инкапсуляцию и явно реализовать 20 новых методов.В то же время мы уже сталкиваемся с ошибками, когда другие люди, использующие эту пользовательскую коллекцию, облажают ее, используя базовые методы ObservableCollection, которые мы не поддерживаем, но не можем скрыть с помощью наследования.