Когда Вы подписываетесь на событие в.NET, подписка добавляется к многоадресному делегату. Когда событие запущено, делегатов звонят в порядке, они были подписаны.
Я хотел бы переопределить подписку так или иначе, так, чтобы подписки были на самом деле запущены в обратный порядок. Это может быть сделано, и как?
Я думаю, что что-то вроде этого могло бы быть тем, в чем я нуждаюсь?:
public event MyReversedEvent
{
add { /* magic! */ }
remove { /* magic! */ }
}
Контроль, когда и если делегат срабатывает внутри многоадресного делегата
Следующий метод создает многоадресный делегат с именем 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])();
}
}
Один из вариантов - обработать это, когда вы инициируете событие. Вы можете получить подписчиков на события через Delegate.GetInvocationList и просто вызвать каждого делегата в обратном порядке самостоятельно.
Вам не нужна магия; вам просто нужно отменить сложение.
Запись делегат1 + делегат2
возвращает новый делегат, содержащий метод (ы) в делегат1
, за которым следуют методы в делегат2
.
Например:
private EventHandler myReversedEventField;
public event EventHandler MyReversedEvent
{
add { myReversedEventField = value + myReversedEventField; }
remove { myReversedEventField -= value; }
}
Вам не нужно никакого волшебства в обработчике remove
, если только вы не хотите удалить последнее вхождение этого обработчика вместо первого. (В случае, если один и тот же обработчик добавлялся дважды)