C # How to get added events?

I am sitting in front of my computer, wondering how to get all the added events. I just read a few articles, including the C # Bedtime Story , to better understand the events, and I think I got the main idea now. But still I could not figure out how to get a list of methods / delegates that are executed if the event is fired. Actually, in my case, that would be enough if I knew if any method / delegate was assigned to a particular event. for example: I use Gma.UserActivityMonitor (to connect a keyboard / mouse) Now I want to know HookManager.KeyUp event HookManager.KeyUp not non-zero. If it is zero, a delegate invitation is added. In my case, this is one \ /

 HookManager.KeyUp += new KeyEventHandler(HookManager_KeyUp); 

Edit

code example

 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) { } } } 
+4
source share
2 answers

Pay attention to this console application and, in particular, to the line calling GetInvocationList() . This method returns a list of attached delegates. Each Delegate has a Method property. Each Method property has a Name .

The delegate is yours

 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(); } } 

The delegate is NOT yours

Well, it gets a little dirty, but it gives you the answer you want. Even if the internal implementation uses an EventHandlerList (which is somewhat common), but , I can not guarantee that it will work in absolutely every scenario, because there can be so many different internal representations.

However, hopefully this works for you. As you can see in the example, I use the BackgroundWorker class as my sample class to get a call list for a specific event that I don't have.

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

Finally, although I made some pretty big changes to the code, I have to give credit to Bob Powell for starting me there.

+5
source

I believe that just comparing HookManager.KeyUp with null will give you your answer.

Other than that, although if everything has changed since the last time I looked into it (quite possibly), it’s quite difficult to get an actual list of delegates related to the event. But if the value is null, this means that no delegates are associated with it.

+1
source

Source: https://habr.com/ru/post/1434827/


All Articles