C#使用反射从窗体控件访问事件名称
本文关键字:访问 事件 控件 窗体 反射 | 更新日期: 2023-09-27 18:26:33
我目前正在开发一个正在进行的解决方案,该解决方案采用包含表单的程序集,创建这些表单的实例,然后从中提取控件。到目前为止一切都很好。然而,我收到了另一个请求,我发现这个请求很难实现。
我现在需要做的是在运行时提取与表单上每个控件关联的事件(特别是实际事件名称和事件类型)。为了促进这一点,我创建了一个非常简单的winforms项目来模拟我将在完成的应用程序中所做的事情。
我尝试了各种方法来获得这些事件,到目前为止,我最接近的方法是:
EventHandlerList events = this.button1.GetType()
.GetProperty("Events", BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.Static |
BindingFlags.NonPublic)
.GetValue(this.button1) as EventHandlerList;
在我的按钮中,我为点击和鼠标离开创建了两个事件。当我调试上面的代码并检查事件时,我可以看到我创建的两个事件,但它们存在于"None public members''head"下。
我在调试模式中看到的事件看起来像:
{Method={Void button1_MouseLeave(System.Object,System.EventArgs)}}
根据另一种形式的建议,我尝试了以下方法,看看我是否可以创建一个事件的委托(但没有成功):
var myEvent = events["button1_MouseLeave"];
我不知道从这里到哪里去。我似乎快到了,因为我实际上可以在调试模式下看到事件,但我不确定如何获得它们的名称。
您几乎做到了,只有EventHandlerList是一个不容易提交的链表。您可以在此处查看源代码:http://referencesource.microsoft.com/#System/compmod/system/componentmodel/EventHandlerList.cs
这将为您提供控件(WinForms)的所有已订阅事件
EventHandlerList events = (EventHandlerList)typeof(Component)
.GetField("events", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField)
.GetValue(this);
object current = events.GetType()
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField)[0]
.GetValue(events);
List<Delegate> delegates = new List<Delegate>();
while(current != null)
{
delegates.Add((Delegate)GetField(current,"handler"));
current = GetField(current,"next");
}
静态助手
public static object GetField(object listItem, string fieldName)
{
return listItem.GetType()
.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField)
.GetValue(listItem);
}