Порядок выполнения обработчиков одного события не может контролироваться с помощью основного поведения самого встроенного события. MulticastDelegates - это «мешки» обработчиков, и они просто захватывают их по одному за раз. Помните, что именно так большинство разработчиков ожидают, что это сработает, и может быть опасно разрешать обработчики событий, зависящие от порядка. Обработчики событий обычно не должны знать друг о друге, потому что, если они зависят от выполнения до или после другого обработчика, они сначала должны знать о существовании другого обработчика (нарушая сокрытие информации и некоторые другие принципы проектирования), и, во-вторых, если этот порядок изменится, поведение будет нарушено.
Если вы понимаете все это и по-прежнему хотите контролировать порядок выполнения обработчиков события, вам будет предложено следующее.
- Создайте упорядоченную коллекцию делегатов типа обработчика событий с именем MyHandlers. Это будет суррогатом для реализации фактического события MulticastDelegate.
- Создайте «основной» метод-обработчик, который на самом деле будет присоединен к встроенному событию, будет перебирать 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 (все, что было вставлено, выполняются первыми, в обратном порядке. они были вставлены). Если вы поместите этот код в пользовательский элемент управления с помощью кнопки, вы можете даже назвать пользовательское событие в элементе управления Click, и элемент управления будет выглядеть и работать так же, как содержащаяся в нем кнопка, за исключением того, что он будет иметь дополнительный элемент управления для вставки. обработчики. Прелесть всего этого в том, что ничто в этом коде не заставляет потребителей работать с ним как с чем-то иным, кроме простого ванильного события.