Зарегистрируйтесь в ObservableCollection <AnyType>.CollectionChanged, не зная универсального типа? - PullRequest
0 голосов
/ 01 мая 2018

У меня есть один "базовый" класс, в котором я хочу наблюдать за любыми изменениями.

Для всех свойств, я иду через GetValue<T>() и SetValue<T>(). Тогда у меня есть Dictionary поле поддержки, сохраненное с ключом CallerMemberName.

При выполнении SetValue<T>() мне бы хотелось, чтобы T было ObservableCollection<AnyThing> для регистрации на событие CollectionChanged (или отмены регистрации предыдущего значения).

Есть идеи, как мне этого добиться?

public void RegisterIfObservable<T>(T value){
    Type type = typeof(T);
    if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ObservableCollection<>)){
        //TODO Register
    }   
}

Целью будет создание объекта при каждой вставке / удалении

new UndoableListAddAction<TU>(ObservableCollection<TU> collection, TU addedElement)

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

У вас может быть вспомогательный метод public void RegisterObservable<T>(IObservable<T> value) {}, который вы называете через отражение:

public void RegisterIfObservable<T>(T value){
    Type type = value.GetType(); 
    // I don't think you can simply use typeof(T) instead of value.GetType() here
    // if the compiler does not know for certain at compile time 
    // whether T will be an IObservable. 
    // And if you DO know that at compile time, then use the alternative solution below.

    if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ObservableCollection<>))
    {
        Type genericArgument = type.GetGenericArguments()[0];
        MethodInfo method = this.GetType().GetMethod("RegisterObservable"); 
        // instead of this.GetType() you could use the type
        // of a helper class where RegisterObservable is located

        MethodInfo genericMethod = method.MakeGenericMethod(genericArgument);
        genericMethod.Invoke(this, new object[]{value});
    }
}

Это каждый раз требует много размышлений, хотя решение Mattis, вероятно, будет быстрее и проще в отладке.


Альтернативное решение:

Вы, вероятно, хотите вызвать RegisterIfObservable только для ICollection<T> или IEnumerable<T>, а не только для любого объекта.

Если ваш метод RegisterIfObservable может быть внутри общего класса, и вы уже знаете тип элементов, вы можете сделать это без отражения:

public class HelperClass<TU>
{
    public void RegisterIfObservable<T>(T value) where T: ICollection<TU>
    {
        var obs = value as ObservableCollection<T>;
        if (obs!=null)
        {
           ...
        }

    }
}
0 голосов
/ 01 мая 2018

Событие CollectionChanged доступно через интерфейс INotifyCollectionChanged, который реализует ObservableCollection<T>. Вы можете просто использовать это, а также избавиться от всех проверок с помощью Type.

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