动态分配事件处理程序:可能吗?
在软件开发中,事件处理程序对于在 UI 元素之间建立事件驱动的交互至关重要和底层代码。然而,出现了一个常见问题:是否可以“窃取”分配给一个控件的事件处理程序并将其分配给另一个控件?
编译器的限制
分配时使用 = 运算符的事件处理程序,编译器会限制已分配的事件处理程序的分配。尝试为 btn2 重用分配给 btn1 的事件处理程序将导致编译器错误。
反思:解决方案路径
尽管编译器有限制,但这确实是可能的使用反射在运行时传输事件处理程序。此方法需要直接访问控制类的私有和内部成员。
代码示例
考虑以下代码片段:
using System; using System.ComponentModel; using System.Windows.Forms; using System.Reflection; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); button1.Click += new EventHandler(button1_Click); // Get secret click event key FieldInfo eventClick = typeof(Control).GetField("EventClick", BindingFlags.NonPublic | BindingFlags.Static); object secret = eventClick.GetValue(null); // Retrieve the click event PropertyInfo eventsProp = typeof(Component).GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance); EventHandlerList events = (EventHandlerList)eventsProp.GetValue(button1, null); Delegate click = events[secret]; // Remove it from button1, add it to button2 events.RemoveHandler(secret, click); events = (EventHandlerList)eventsProp.GetValue(button2, null); events.AddHandler(secret, click); } void button1_Click(object sender, EventArgs e) { MessageBox.Show("Yada"); } } }
在此代码中,检索秘密内部事件密钥并用于访问 btn1 的事件处理程序列表。然后,事件处理程序从 btn1 中删除并添加到 btn2。
复杂性和限制
虽然反射提供了一种传输事件处理程序的方法,但需要注意的是这种方法很复杂,应谨慎使用。它涉及访问控制类的内部实现细节,这些细节可能会在框架的不同版本中发生变化。
以上是C# 中的事件处理程序可以动态重新分配吗?的详细内容。更多信息请关注PHP中文网其他相关文章!