c#如何获得附加事件?

c#如何获得附加事件?,c#,events,delegates,C#,Events,Delegates,我坐在我的电脑前,想知道如何获得所有添加的事件。我刚刚读了一些文章,包括为了更好地理解事件,我想我现在明白了主要的意思。但我仍然不知道如何获取在触发事件时执行的方法/委托列表。事实上,在我的例子中,如果我知道是否有任何方法/委托被分配给某个事件就足够了。 例如:我正在使用Gma.UserActivityMonitor(用于键盘/鼠标挂钩) 现在我想知道事件HookManager.KeyUp事件是否不是null。 如果为空,则将添加一个委托。就我而言,这个\/ HookManager.KeyUp

我坐在我的电脑前,想知道如何获得所有添加的事件。我刚刚读了一些文章,包括为了更好地理解事件,我想我现在明白了主要的意思。但我仍然不知道如何获取在触发事件时执行的方法/委托列表。事实上,在我的例子中,如果我知道是否有任何方法/委托被分配给某个事件就足够了。 例如:我正在使用
Gma.UserActivityMonitor
(用于键盘/鼠标挂钩) 现在我想知道事件
HookManager.KeyUp
事件是否不是null。 如果为空,则将添加一个委托。就我而言,这个\/

HookManager.KeyUp += new KeyEventHandler(HookManager_KeyUp);
编辑 示例代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using Gma.UserActivityMonitor;

namespace EventTest 
{ 
    public partial class Form1 : Form 
    { 
        public Form1() 
        { 
            InitializeComponent();             
            HookManager.KeyUp += new KeyEventHandler(HookManager_KeyUp);
            Delegate[] a = GetEventSubscribers(button1, "Click");
            label1.Text = a[0].Method.ToString();
        } 
        void HookManager_KeyUp(object sender, KeyEventArgs e) 
        {         
            /* Do something*/     
        } 
        bool NoEventAttached() 
        { 
            return false; 
        }

        public static Delegate[] GetEventSubscribers(object target, string eventName) 
        { 
            Type t = target.GetType(); 
            var eventInfo = t.GetEvent(eventName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); 

            do 
            { 
                FieldInfo[] fia = t.GetFields(
                    BindingFlags.Static | 
                    BindingFlags.Instance | 
                    BindingFlags.NonPublic); 

                foreach (FieldInfo fi in fia) 
                { 
                    if (fi.Name == eventName) 
                    { 
                        Delegate d = fi.GetValue(target) as Delegate;                         
                        if (d != null)                         
                            return d.GetInvocationList(); 
                    } 
                    else if (fi.FieldType == typeof(EventHandlerList)) 
                    { 
                        ----> var obj = fi.GetValue(target) as EventHandlerList; 
                        var eventHandlerFieldInfo = obj.GetType().GetField("head", BindingFlags.Instance | BindingFlags.NonPublic); 
                        do 
                        { 
                            var listEntry = eventHandlerFieldInfo.GetValue(obj); 
                            var handler = listEntry.GetType().GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic); 
                            if (handler != null) 
                            { 
                                var subD = handler.GetValue(listEntry) as Delegate; 
                                if (subD.GetType() != eventInfo.EventHandlerType) 
                                { 
                                    eventHandlerFieldInfo = listEntry.GetType().GetField("next", BindingFlags.Instance | BindingFlags.NonPublic); 
                                    obj = listEntry as EventHandlerList; <-----------
                                    continue; 
                                } 
                                if (subD != null) 
                                { 
                                    return subD.GetInvocationList(); 
                                } 
                            } 
                        } 
                        while (eventHandlerFieldInfo != null);                 
                    } 
                } 
                t = t.BaseType; 
            } while (t != null);          
            return new Delegate[] { }; 
        }

        private void button1_Click(object sender, EventArgs e)
        {

        }

        private void button1_MouseClick(object sender, MouseEventArgs e)
        {

        }


    } 
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
运用系统反思;
使用Gma.UserActivityMonitor;
命名空间事件测试
{ 
公共部分类Form1:Form
{ 
公共表格1()
{ 
初始化组件();
HookManager.KeyUp+=新的KeyEventHandler(HookManager\u KeyUp);
委托[]a=GetEventSubscribers(按钮1,“单击”);
label1.Text=a[0]。方法.ToString();
} 
void HookManager\u KeyUp(对象发送方,KeyEventArgs e)
{         
/*做点什么
} 
bool NoEventAttached()
{ 
返回false;
}
公共静态委托[]GetEventSubscribers(对象目标,字符串eventName)
{ 
类型t=target.GetType();
var eventInfo=t.GetEvent(eventName,BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
做
{ 
FieldInfo[]fia=t.GetFields(
BindingFlags.Static|
BindingFlags.Instance|
BindingFlags(非公开);
foreach(fia中的FieldInfo fi)
{ 
如果(fi.Name==eventName)
{ 
委托d=fi.GetValue(目标)作为委托;
如果(d!=null)
返回d.GetInvocationList();
} 
else if(fi.FieldType==typeof(EventHandlerList))
{ 
---->var obj=fi.GetValue(目标)作为EventHandlerList;
var eventHandlerFieldInfo=obj.GetType().GetField(“head”,BindingFlags.Instance | BindingFlags.NonPublic);
做
{ 
var listEntry=eventHandlerFieldInfo.GetValue(obj);
var handler=listEntry.GetType().GetField(“handler”,BindingFlags.Instance | BindingFlags.NonPublic);
if(处理程序!=null)
{ 
var subD=handler.GetValue(listEntry)作为委托;
if(subD.GetType()!=eventInfo.EventHandlerType)
{ 
eventHandlerFieldInfo=listEntry.GetType().GetField(“下一步”,BindingFlags.Instance | BindingFlags.NonPublic);

obj=listEntry as EventHandlerList;我相信只要将HookManager.KeyUp与null进行比较就可以得到答案


但除此之外,除非自上次我调查以来情况有所改变(很可能)获取与事件关联的委托的实际列表相当困难。但是如果该值为null,则表明没有委托与事件关联。

请注意此控制台应用程序,特别是调用
GetInvocationList()的行
。该方法返回附加的代理列表。每个
代理
都有一个
方法
属性。每个
方法
属性都有一个
名称

委托人为您所有 委托不属于您 好吧,这有点混乱,但它得到了您想要的答案。即使内部实现使用了
EventHandlerList
(这有点常见),但是我不能保证它绝对适用于所有场景,因为可能有很多不同的内部表示

但是,希望这对您有用。正如您在示例中看到的,我使用
BackgroundWorker
类作为示例类,用于获取我不拥有的特定事件的调用列表

using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

internal class Program
{
    private static void Main(string[] args)
    {
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.DoWork += new DoWorkEventHandler(worker_DoWork2);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);

        Console.WriteLine(string.Join(" | ", GetEventSubscribers(worker, "DoWork").Select(d => d.Method.Name).ToArray()));
    }

    static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        throw new NotImplementedException();
    }

    static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        throw new NotImplementedException();
    }

    static void worker_DoWork2(object sender, DoWorkEventArgs e)
    {
        throw new NotImplementedException();
    }

    static void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        throw new System.NotImplementedException();
    }

    public static Delegate[] GetEventSubscribers(object target, string eventName)
    {
        Type t = target.GetType();
        var eventInfo = t.GetEvent(eventName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);

        do
        {
            FieldInfo[] fia = t.GetFields(
                 BindingFlags.Static |
                 BindingFlags.Instance |
                 BindingFlags.NonPublic);

            foreach (FieldInfo fi in fia)
            {
                if (fi.Name == eventName)
                {
                    Delegate d = fi.GetValue(target) as Delegate;
                    if (d != null)
                        return d.GetInvocationList();
                }
                else if (fi.FieldType == typeof(EventHandlerList))
                {
                    dynamic obj = fi.GetValue(target) as EventHandlerList;
                    var eventHandlerFieldInfo = obj.GetType().GetField("head", BindingFlags.Instance | BindingFlags.NonPublic);
                    do
                    {
                        var listEntry = eventHandlerFieldInfo.GetValue(obj);
                        var handler = listEntry.GetType().GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic);
                        if (handler != null)
                        {
                            var subD = handler.GetValue(listEntry) as Delegate;
                            if (subD.GetType() != eventInfo.EventHandlerType)
                            {
                                eventHandlerFieldInfo = listEntry.GetType().GetField("next", BindingFlags.Instance | BindingFlags.NonPublic);
                                obj = listEntry;
                                continue;
                            }
                            if (subD != null)
                            {
                                return subD.GetInvocationList();
                            }
                        }
                    }
                    while (eventHandlerFieldInfo != null);
                }
            }

            t = t.BaseType;
        } while (t != null);

        return new Delegate[] { };
    }
}

最后,虽然我对代码做了一些相当大的修改,但我必须给出一些帮助我开始这项工作。

仅供参考,我添加了一个示例,演示如何获取事件的调用列表。这似乎是我正在寻找的^^^让我们看看它是否有效:PHmm我不知道如何使用静态事件oO我必须编辑外部dll,我的意思是我必须将其添加到实现该事件的类中吗?@lorenzalbert:你不应该这样做,这是一个
公共虚拟
方法。嗯,也许你可以在我的编辑中帮助我使用给定的示例代码。除了使用
getInvocationList
访问委托列表之外,我什么都懂。我的意思是你添加了event CheckInvocationList如果我这样做,我可以访问代理,但我不知道如何将所有内容关联起来以使其正常工作。编辑您的问题,并在此时发布您拥有的代码(调用GetInvocationList),我将尝试提供帮助。
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

internal class Program
{
    private static void Main(string[] args)
    {
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.DoWork += new DoWorkEventHandler(worker_DoWork2);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);

        Console.WriteLine(string.Join(" | ", GetEventSubscribers(worker, "DoWork").Select(d => d.Method.Name).ToArray()));
    }

    static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        throw new NotImplementedException();
    }

    static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        throw new NotImplementedException();
    }

    static void worker_DoWork2(object sender, DoWorkEventArgs e)
    {
        throw new NotImplementedException();
    }

    static void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        throw new System.NotImplementedException();
    }

    public static Delegate[] GetEventSubscribers(object target, string eventName)
    {
        Type t = target.GetType();
        var eventInfo = t.GetEvent(eventName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);

        do
        {
            FieldInfo[] fia = t.GetFields(
                 BindingFlags.Static |
                 BindingFlags.Instance |
                 BindingFlags.NonPublic);

            foreach (FieldInfo fi in fia)
            {
                if (fi.Name == eventName)
                {
                    Delegate d = fi.GetValue(target) as Delegate;
                    if (d != null)
                        return d.GetInvocationList();
                }
                else if (fi.FieldType == typeof(EventHandlerList))
                {
                    dynamic obj = fi.GetValue(target) as EventHandlerList;
                    var eventHandlerFieldInfo = obj.GetType().GetField("head", BindingFlags.Instance | BindingFlags.NonPublic);
                    do
                    {
                        var listEntry = eventHandlerFieldInfo.GetValue(obj);
                        var handler = listEntry.GetType().GetField("handler", BindingFlags.Instance | BindingFlags.NonPublic);
                        if (handler != null)
                        {
                            var subD = handler.GetValue(listEntry) as Delegate;
                            if (subD.GetType() != eventInfo.EventHandlerType)
                            {
                                eventHandlerFieldInfo = listEntry.GetType().GetField("next", BindingFlags.Instance | BindingFlags.NonPublic);
                                obj = listEntry;
                                continue;
                            }
                            if (subD != null)
                            {
                                return subD.GetInvocationList();
                            }
                        }
                    }
                    while (eventHandlerFieldInfo != null);
                }
            }

            t = t.BaseType;
        } while (t != null);

        return new Delegate[] { };
    }
}