通过反射获取事件

8

我正在尝试通过反射获取按钮的点击事件,以下是我的代码:

Assembly assem = Assembly.GetExecutingAssembly();

Type tExForm = btnSave.GetType();
Object exFormAsObj = Activator.CreateInstance(tExForm);

EventInfo evClick = tExForm.GetEvent("Click");
Type tDelegate = evClick.EventHandlerType;

MethodInfo miHandler=
btnSave.GetType().GetMethod("Click",
BindingFlags.NonPublic | BindingFlags.Instance);

Delegate d = Delegate.CreateDelegate(tDelegate, btnSave, miHandler);

MethodInfo addHandler = evClick.GetAddMethod();
Object[] addHandlerArgs = { d };
addHandler.Invoke(exFormAsObj, addHandlerArgs);

然而,miHandler变量总是为空!

注意:我关心的主要问题是如何在运行时调用特定控件的事件,有没有办法?例如,当用户按F1键时,我想选择触发哪个单击事件。


1
你的 miHandler 定义在哪里? - milagvoniduak
抱歉,打字错误了。我已经更正了代码,miHandler 的类型是 MethodInfo。 - Hasan Shouman
BindingFlags.NonPublic? - qxg
你正在尝试获取一个点击事件。按钮上没有名为“Click”的方法,你为什么要调用“GetMethod”? - Yuval Itzchakov
所以...你是在尝试通过反射实际“触发”Click事件吗? - Rex M
显示剩余2条评论
2个回答

7

根据问题下面的额外评论,真正的目标是通过反射来触发事件。

我要先说一下这几乎肯定是一个非常糟糕的想法。它容易出错且脆弱,只会引起错误。相反,我建议有许多事件处理程序(按钮点击处理程序、按键事件处理程序等),所有处理程序都调用一个共同的方法,该方法执行您想要的实际操作。

话虽如此,以下是如何做到的。反射始终很脆弱,这是其主要例子 - 您必须依赖于.NET中事件如何工作的当前实现细节,这可能会在明天改变,从而停止工作。您可以获取存储在对象上的私有字段,其中包含对所有订阅事件处理程序的引用,遍历每个处理程序并调用它。您还需要手动创建将传递的参数(例如EventArgs):

var eventArgs = EventArgs.Empty; //replace with real args

var eventInfo = tExForm.GetType().GetEvent("Click", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var eventDelegate = (MulticastDelegate)tExForm.GetType().GetField("Click", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(tExForm);
if (eventDelegate != null)
{
  foreach (var handler in eventDelegate.GetInvocationList())
  {
    handler.Method.Invoke(handler.Target, new object[] { tExForm, eventArgs });
  }
}

3

你应该包括 BindingFlag.FlattenHierarchy,因为 Click 是在 Control 上定义的,而不是在 Button 上定义的。

EventInfo miHandler =
  btnSave.GetType(). GetEvent("Click",
  BindingFlags.FlattenHierarchy | BindingFlags.Instance);

1
“Click”不是一个方法,所以“GetMethod()”仍然会返回null。 - Rex M
@RexM:太简单了,我竟然忽略了。已更新。 - Patrick Hofman
我不确定这会解决 OP 的问题。 - Rex M
这里没有编译器,所以我不完全确定,但我认为miHandler现在不应该为空了。 - Patrick Hofman
1
据我理解,OP并没有遇到获取Click事件信息的问题,他遇到的问题是获取事件委托的MethodInfo。 - Rex M
@PatrickHofman 我尝试了 BindingFlag.FlattenHierarchy,但是没有起作用! - Hasan Shouman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接