Порядка выполнения обработчиков одного события не может контролироваться с помощью основного поведения встроенного самого события. MulticastDelegates - это «сумки» обработчиков, и они просто захватывают их по одному. Имейте в виду, что так большинство разработчиков ожидают, что это сработает, и может быть опасно разрешать обработчики событий, зависящие от порядка. Обработчики событий обычно не знают друг о друге, потому что, если они зависят от выполнения перед или после другого обработчика, они сначала должны знать о существовании другого обработчика (нарушая скрытие информации и несколько других принципов проектирования), а во-вторых, если этот порядок изменится, поведение будет нарушено.
Если вы все это понимаете и по-прежнему хотите контролировать порядок выполнения обработчиков события, то вам будет близко.
- Создайте упорядоченную коллекцию делегатов типа обработчика событий, называемого MyHandlers. Это будет суррогатом для реализации события MulticastDelegate.
- Создайте метод обработчика «master», который фактически будет прикреплен к встроенному событию и будет проходить через MyHandlers и вызовет каждый из них.
- Определите некоторые средства для добавления и удаления обработчиков из списка. Некоторое из этого может быть выполнено с помощью специального свойства «свойство», но это будет определять только добавление и удаление поведения, а не вставку.
Код может выглядеть следующим образом:
private List<EventHandler> MyHandlers = new List<EventHandler>();
private void MasterClickHandler(object sender, EventArgs e)
{
foreach(var handler in MyHandlers)
handler(sender, e);
}
public event EventHandler MyControlButtonClick
{
add { MyHandlers.Add(value); }
remove { MyHandlers.Remove(value); }
}
public void InsertButtonClickHandler(EventHandler handler)
{
MyHandlers.Insert(handler,0); //calling this to add a handler puts the handler up front
}
...
myForm.MyControl.Click += MasterClickHandler;
Обратите внимание, что вы больше не прикрепляться, кроме MasterClickHandler обработчики фактического события; вы не можете иметь свой торт и есть его тоже, как переопределяя, так и сохраняя основное поведение событий.Также нет «вставки» поведения, встроенного в «свойство» события; вы должны определить метод, который позволяет это. Наконец, вы никогда не должны поднимать событие MyControlButtonClick напрямую (хотя, поскольку ваш контроль является единственным, который может, это может быть принудительно проверено кодом).
Теперь, когда вы нажимаете кнопку, встроенное событие Click кнопки запускает MasterEventHandler, который будет выполнять делегаты в MyHandlers в том же порядке, в каком они были прикреплены к MyControlButtonClick (с любыми вставками, выполненными сначала, в обратном порядке чтобы они были вставлены). Если вы разместили этот код в пользовательском элементе управления с помощью кнопки, вы можете даже назвать настраиваемое событие на своем элементе управления. Нажмите, и элемент управления будет выглядеть и работать так же, как и содержащаяся в нем кнопка, за исключением того, что она будет иметь дополнительный контроль над вставкой обработчики. Красота всего этого заключается в том, что ничто об этом коде не заставляет потребителей работать с ним, как что-то другое, кроме простого ванильного события.
+1 для хорошего совета. –