Отмена подписки или проверка события CollectionChanged с помощью отражения - PullRequest
0 голосов
/ 25 ноября 2018

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

Код здесь:

foreach (PropertyInfo propertyInfo in props)
{
    nType = this.GetPropertyInfoTypeObs(propertyInfo.PropertyType);

    if (nType == Static_Enums.TypeEnums.TYPE_OBSERVABLE_COLLECTION)
    {
        var genargs = propertyInfo.PropertyType.GetGenericArguments();

        var o = propertyInfo.GetValue(this, null);

        EventInfo evi = o.GetType().GetEvent("CollectionChanged", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        var eventHandler = new Action<object, NotifyCollectionChangedEventArgs>(
                    (s, a) =>
                    {
                        // Event code here
                        this.MakePropertyDirty(propertyInfo.Name);
                    });

        var del = Delegate.CreateDelegate(evi.EventHandlerType, eventHandler.Target, eventHandler.Method);

        evi.AddEventHandler(o, del);
    }
}

Как уже говорилось, эта часть работает нормально.Но как решить проблему с добавлением события более одного раза?

Сначала я попробовал просто набрать evi.RemoveEventHandler(o, del) в строке выше.Это не работает для меня - как, например, если я смотрю, что происходит, когда эта строка выполняется, обработчик событий, кажется, остается нетронутым.Возможно, я делаю это неправильно?

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

Редактировать

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

Затем я пошел немного дальше и попытался сделать это:

EventInfo ef = o.GetType().GetEvent("CollectionChanged");
MethodInfo rem = ef.GetRemoveMethod();
ParameterInfo[] piList = rem.GetParameters();

object[] oList = new object[1];
oList[0] = storedProc;

rem.Invoke(o, oList);

К сожалению, это тоже не помогает.

Кроме того, я прочитал, что для удаления обработчика, он должен быть точно таким же обработчик в методе удаления.Теперь в этом методе производный класс имеет более одного ObservableCollection.Поэтому я попытался ограничить создание нового делегата (и присвоить его свойству класса) только в случае с особо названным ObservableCollection (который, как я знал, появится).Я проследил это снова, по одной строке за раз, и обработчик событий не был удален.

Однако даже если бы это работало, мне пришлось бы хранить делегат для каждого ObservableCollection, для которогоЯ сделал это.Боже мой, я не могу просто сказать это, чтобы очистить событие?

...