如何从EventInfo获取委托对象?

Bru*_*oLM 10 .net c# reflection

我需要从当前类中获取所有事件,并找出订阅它的方法.在这里,我得到了一些关于如何做到这一点的答案,但我不知道如何才能得到delegate我所拥有的是什么EventInfo.

var events = GetType().GetEvents();

foreach (var e in events)
{
    Delegate d = e./*GetDelegateFromThisEventInfo()*/;
    var methods = d.GetInvocationList();
}
Run Code Online (Sandbox Code Playgroud)

是否有可能获得代表EventInfo?怎么样?

Eni*_*ity 12

该语句var events = GetType().GetEvents();将为您EventInfo提供与当前类型关联的对象列表,而不是当前实例本身.因此,该EventInfo对象不包含有关当前实例的信息,因此它不知道有线代理.

要获取所需信息,您需要获取当前实例上事件处理程序的支持字段.这是如何做:

public class MyClass
{
    public event EventHandler MyEvent;

    public IEnumerable<MethodInfo> GetSubscribedMethods()
    {
        Func<EventInfo, FieldInfo> ei2fi =
            ei => this.GetType().GetField(ei.Name,
                BindingFlags.NonPublic |
                BindingFlags.Instance |
                BindingFlags.GetField);

        return from eventInfo in this.GetType().GetEvents()
               let eventFieldInfo = ei2fi(eventInfo)
               let eventFieldValue =
                   (System.Delegate)eventFieldInfo.GetValue(this)
               from subscribedDelegate in eventFieldValue.GetInvocationList()
               select subscribedDelegate.Method;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以现在你的调用代码看起来像这样:

class GetSubscribedMethodsExample
{
    public static void Execute()
    {
        var instance = new MyClass();
        instance.MyEvent += new EventHandler(MyHandler);
        instance.MyEvent += (s, e) => { };

        instance.GetSubscribedMethods()
            .Run(h => Console.WriteLine(h.Name));
    }

    static void MyHandler(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的输出是:

MyHandler
<Execute>b__0
Run Code Online (Sandbox Code Playgroud)

如果您希望返回代理而不是方法信息等,我相信您可以使用代码进行浏览.

我希望这有帮助.


Les*_*Les 5

与Enigmativity类似,可以找到其他类的调用列表,而不仅仅是当前类......

    private void testit()
    {
        WithEvents we = new WithEvents();
        we.myEvent += new EventHandler(we_myEvent);
        we.myEvent += new EventHandler(we_myEvent2);

        foreach (EventInfo ev in we.GetType().GetEvents())
        {
            FieldInfo fi = we.GetType().GetField(ev.Name, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
            Delegate del = (Delegate)fi.GetValue(we);
            var list = del.GetInvocationList();
            foreach (var d in list)
            {
                Console.WriteLine("{0}", d.Method.Name);
            }
        }
    }

    void we_myEvent(object sender, EventArgs e)
    {
    }
    void we_myEvent2(object sender, EventArgs e)
    {
    }


public class WithEvents
{
    public event EventHandler myEvent;
}
Run Code Online (Sandbox Code Playgroud)

...只要在类中声明事件处理程序,就像我们上面看到的那样。但请考虑Control类,其中 EventHandlerList 存储在“Events”属性中,并且每个事件字段名称均以“Event”开头,后跟事件名称。然后是 Form 派生类,它们管理事件的方式似乎有所不同。值得深思。