gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-30 00:54:32 25 4
gpt4 key购买 nike

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

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)列表。每个 Delegate 都有一个 Method 属性。每个 Method 属性都有一个 Name

委托(delegate)归你所有

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

委托(delegate)不属于你

好吧,这有点困惑,但它可以为您提供所需的答案。即使内部实现使用 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[] { };
}
}

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

关于c#如何获取添加的事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12476088/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com