3

我想创建一些自定义事件,它们总是以事件注册的相反顺序调用注册的事件处理程序,即总是首先调用最近注册的事件处理程序。可能吗?这些事件将由业务层类在某些错误条件下引发,其中注册的事件处理程序可能能够克服错误条件。

这是一个纯粹的技术问题,是否可以这样做?是否可以覆盖事件链调用顺序?语言(C# 2.0、3.0、4.0 的任何版本)是否支持此功能?

编辑:

可能的用途是尽可能用于错误报告和错误恢复。例如,Func A 调用 Func B,Func B 又调用 Func C。Func C 可能会遇到错误情况并有相应的事件。如果 Func A 和 Func B 能够提供错误恢复机制,它们就会注册该事件。由于 Func B 更有可能具有解决错误的上下文,因此我想调用最近注册的处理程序并检查事件参数以查看错误是否已解决。如果是,我什至不会调用其他事件处理程序。如果不是,我将调用第二个最近注册的处理程序,这将是调用者的调用函数,即 Func A。

在大多数情况下,代码的结构通常是这样的:如果 Func A 调用 Func B,那么 Func B 不会调用 Func A,即通常不存在循环调用,并且事件处理程序的顺序将与函数调用的顺序相同。因此,如果 Func A 调用 Func B,而 Func B 又调用了 Func C,而 Func C 引发了一个“错误事件”,则最适合处理错误的候选者是 Func B 的事件处理程序,其次是 Func A 的事件处理程序,依此类推。

它就像堆栈跟踪的展开,并让最近的调用函数有机会消费事件。任何没有。调用者函数可能在那里。

在任何处理程序成功使用该事件后,引发“错误事件”的 Func C 将继续执行。它将检查事件参数以确定这一点。如果没有处理程序使用该事件,Func C 将抛出异常。

4

1 回答 1

4

是的,您可以使用 MulticastDelegate.GetInvocationList() 方法自己迭代事件的调用列表。像这样:

    public event EventHandler Custom;

    protected virtual void OnCustom(EventArgs e) {
        var handler = Custom;
        if (handler != null) {
            var subscribers = handler.GetInvocationList();
            for (int ix = subscribers.Length - 1; ix >= 0; --ix) {
                var sub = (EventHandler)subscribers[ix];
                sub(this, e);
            }
        }
    }

请注意,这是一个不确定的解决方案,您无法控制其他代码订阅事件的顺序。

于 2013-03-08T19:02:39.767 回答