Проблема в том, что Delegate
s являются неизменными.
Если вы добавляете обработчик к событию, он создает новый экземпляр Delegate
, который содержит старые обработчики и вновь добавленный обработчик. Старый Delegate
не изменяется и отбрасывается.
Когда я пишу, value.AnEvent += AnEvent
, он добавляет Delegate
, содержащий текущие обработчики (если есть), к событию внутреннего класса. Однако изменения в событии внешнего класса игнорируются, потому что они не изменяют экземпляр Delegate
, который я добавил в событие внутреннего класса. Аналогично, если я удаляю обработчик после установки свойства Inner
, обработчик не удаляется из события внутреннего класса.
Есть два правильных способа сделать это.
Я могу сделать свой собственный обработчик, который вызывает событие оболочки, например:
public event EventHandler AnEvent;
public OtherClass Inner {
get { /* ... */ }
set {
if(Inner != null)
Inner.AnEvent -= Inner_AnEvent;
//...
if(value != null)
value.AnEvent += Inner_AnEvent;
//...
}
}
void Inner_AnEvent(object sender, EventArgs e) {
var handler = AnEvent;
if (handler != null) handler(sender, e);
}
Другой способ - создать пользовательское событие в оболочке, которое добавляет его обработчики к событию внутреннего класса, например:
EventHandler anEventDelegates
public OtherClass Inner {
get { /* ... */ }
set {
//...
if(value != null)
value.AnEvent += anEventDelegates;
//...
}
}
public event EventHandler AnEvent {
add {
anEventDelegates += value;
if (Inner != null) Inner.AnEvent += value;
}
remove {
anEventDelegates -= value;
if(Inner != null) Inner -= value;
}
}
Обратите внимание, что это не совсем потокобезопасно.
Я решил эту проблему сам и выкладываю вопрос и ответ в пользу людей с похожими проблемами.