Могу ли я изменить порядок событий делегата многоадресной передачи?
При подписке на событие в .NET подписка добавляется к многоадресному делегату. Когда событие запущено, делегаты вызываются в том порядке, в котором они были подписаны.
Я хотел бы как-то переопределить подписку, так что подписки действительно запускаются в обратном порядке. Можно ли это сделать и как?
Я думаю, что что-то вроде этого может быть тем, что мне нужно?:
public event MyReversedEvent
{
add { /* magic! */ }
remove { /* magic! */ }
}
Ответы
Ответ 1
Управление, когда и если делегат срабатывает внутри делегата многоадресной передачи
Следующий метод создает делегат многоадресной рассылки, называемый allInstances, а затем использует GetInvocationList, чтобы каждый делегат мог быть запущен индивидуально, в обратном порядке:
public static void InvokeInReverse()
{
MyDelegate myDelegateInstance1 = new MyDelegate(TestInvoke.Method1);
MyDelegate myDelegateInstance2 = new MyDelegate(TestInvoke.Method2);
MyDelegate myDelegateInstance3 = new MyDelegate(TestInvoke.Method3);
MyDelegate allInstances =
myDelegateInstance1 +
myDelegateInstance2 +
myDelegateInstance3;
Console.WriteLine("Fire delegates in reverse");
Delegate[] delegateList = allInstances.GetInvocationList();
for (int counter = delegateList.Length - 1; counter >= 0; counter--)
{
((MyDelegate)delegateList[counter])();
}
}
Ответ 2
Вам не нужна магия; вам просто нужно отменить добавление.
Написание delegate1 + delegate2
возвращает новый делегат, содержащий метод в delegate1
, за которым следуют методы в delegate2
.
Например:
private EventHandler myReversedEventField;
public event EventHandler MyReversedEvent
{
add { myReversedEventField = value + myReversedEventField; }
remove { myReversedEventField -= value; }
}
Вам не нужна магия в обработчике remove
, если вы не хотите удалить последнее вхождение этого обработчика вместо первого. (Если один и тот же обработчик был добавлен дважды)
Ответ 3
Один из вариантов заключается в том, чтобы справиться с этим, когда вы поднимаете событие. Вы можете получить подписчиков событий через Delegate.GetInvocationList и просто вызвать каждого делегата в обратном порядке.