问题描述
我坐在我的电脑前想知道如何获取所有添加的事件.我刚刚阅读了一些文章,包括 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#如何获取添加的事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!