c#如何获取添加的事件?

c# How to get added events?(c#如何获取添加的事件?)
本文介绍了c#如何获取添加的事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am sitting infront of my pc wondering how to get all added events. I just read some articles including A C# Bedtime Story to better understand events and I think that I got the main idea now. But still I couldn't figure out how to get the List of methods/delegates that are executed if an event is fired. Actually in my case it'd be enough if I knew if any method/delegate is assigned to a certain event. for example: I am using Gma.UserActivityMonitor (for keyboard/mouse-hooking) Now I want to know if the event HookManager.KeyUp event is not null. If it is null a delegate shout be added. In my case this one /

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)
        {

        }


    } 
}

推荐答案

注意这个控制台应用程序,特别是调用 GetInvocationList() 的行.该方法返回附加的委托列表.每个 Delegate 都有一个 Method 属性.每个 Method 属性都有一个 Name.

Take note to this console application, and specifically the line calling GetInvocationList(). That method returns the list of delegates attached. Each Delegate has a Method property. Each Method property has a Name.

internal class Program
{
    public event EventHandler CheckInvocationList;

    private static void Main(string[] args)
    {
        Program p = new Program();
        p.CheckInvocationList += new EventHandler(p_CheckInvocationList);
        p.Method1();

        Console.WriteLine(string.Join(" | ", p.CheckInvocationList.GetInvocationList().Select(d => d.Method.Name).ToArray()));
    }

    static void p_CheckInvocationList(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }

    public void Method1()
    {
        this.CheckInvocationList += new EventHandler(Program_CheckInvocationList);
    }

    void Program_CheckInvocationList(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
}

代理不归你所有

好的,这有点混乱,但它会为您提供您想要的答案.即使内部实现使用 EventHandlerList(这有点常见),但是我不能保证它绝对适用于所有场景,因为可能有很多不同的内部表示.

Delegate is NOT Owned by You

Ok, this gets a little messy, but it gets you the answer you want. Even if the internal implementation uses an EventHandlerList (which is somewhat common), but I cannot gaurantee it would work in absolutely every scenario because there can be so many different internal representations.

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

However, hopefully this will work for you. As you can see in the example I'm using the BackgroundWorker class as my example class for getting the invocation list for a specific event I do not own.

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[] { };
    }
}

最后,虽然我对代码做了一些相当大的修改,但我必须给出 感谢 Bob Powell 让我开始做这件事.

Finally, though I made some pretty big modifications to the code, I have to give credit to Bob Powell for getting me started on this.

这篇关于c#如何获取添加的事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)