Я использовал отражение в своем проекте для добавления событий в 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
, для которогоЯ сделал это.Боже мой, я не могу просто сказать это, чтобы очистить событие?