检查现有的“已连接”方法

3

由于我对这些概念还很陌生,可能会存在一些基本的误解,请耐心听我解释。

目前,我正在从一个事件中删除方法,操作如下:

scheduleView.TouchDown -= scheduleView_TouchDown;

在其他情况下 - 添加方法:

scheduleView.TouchDown += scheduleView_TouchDown;

目前为止一切顺利,我可以理解可以添加多种方法,例如:
scheduleView.TouchDown += scheduleView_TouchDown;
scheduleView.TouchDown += scheduleView_AnotherTouchDownEventHandler;

但我如何随后检查哪些方法已连接到此事件?
3个回答

8
有趣的是,你无法从外部(至少目前还不行)获取一个事件。一个事件只需要提供两个访问器——add和remove。CLI规范定义了其他访问器方法,但在C#或其他地方都没有使用。重点是:我们无法询问一个事件有哪些订阅者(实际上,我们也不需要知道)。你能做的就是:添加或移除。如果你担心重复订阅,那么请注意,如果你尝试取消订阅但实际上没有订阅,那么根据任何理智的实现,这只会是一个无操作;这意味着你可以这样做:
// make sure we are subscribed once but **only** once
scheduleView.TouchDown -= scheduleView_TouchDown;
scheduleView.TouchDown += scheduleView_TouchDown;

从引发事件的代码角度来看,您很少需要知道“谁” - 只需:

// note I'm assuming a "field-like event" implementation here; otherwise,
// change this to refer to the backing-field, or the delegate from the
// event-handler-list
var handler = TouchDown;
if(handler != null) handler(this, EventArgs.Empty); // or similar

还有一种方法可以将代理列表分解为单独的订阅者,但这种情况很少需要:

var handler = TouchDown;
if(handler != null) {
    foreach(EventHandler subscriber in handler.GetInvocationList()) {
        subscriber(this, EventArgs.Empty);
    }
}

这主要用于以下方面:

  • 当您想对每个订阅者分别执行异常处理时
  • 当委托返回一个值或更改状态,并且您需要对每个订阅者进行处理时

谢谢Marc。目前为止,我的代码已经按照你的建议避免了任何可能的重复订阅,我的问题更多是出于好奇。再次感谢。 - user1017882

4

是的:如果您发布事件的类内部,您可以直接访问委托,并调用GetInvocationList方法以获取订阅者列表。

否:如果您在类外部工作,因为委托对您不可见。您可以使用反射来访问它,但这充其量只是一个hack。


1
在声明事件的类型中,您可以使用GetInvocationList()来查找已订阅的委托:
public class EventProvider
{
    public event EventHandler SomeEvent;

    protected virtual void OnSomeEvent(EventArgs args)
    {
        if (SomeEvent != null)
        {
            var delegates = SomeEvent.GetInvocationList();
            foreach (var del in delegates)
            {
                Console.WriteLine("{0} has subscribed to SomeEvent", del.Method.Name);
            }
            SomeEvent(this, args);
        }
    }

    public void RaiseSomeEvent()
    {
        OnSomeEvent(EventArgs.Empty);
    }
}

public class Program
{
    public static void Main()
    {
        EventProvider provider = new EventProvider();
        provider.SomeEvent += Callback1;
        provider.SomeEvent += Callback2;
        provider.RaiseSomeEvent();
    }

    public static void Callback1(object sender, EventArgs e)
    {
        Console.WriteLine("Callback 1!");
    }

    public static void Callback2(object sender, EventArgs e)
    {
        Console.WriteLine("Callback 2!");
    }
}

这将产生以下输出:

Callback1 has subscribed to SomeEvent
Callback2 has subscribed to SomeEvent
Callback 1!
Callback 2!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接