使用代码删除事件处理程序

时间:2011-08-13 19:25:33

标签: c# reflection event-handling

可以使用按钮单击事件中的以下代码删除事件处理程序。

Button btn = new Button();
this.Controls.Add(btn);
btn.Click += (o, x) =>
{
    Button b = o as Button;
    FieldInfo eventclick = typeof(Control).GetField("EventClick", BindingFlags.Static | BindingFlags.NonPublic);
    object eventValue = eventclick.GetValue(b);
    PropertyInfo events = b.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
    EventHandlerList eventHandlerList = (EventHandlerList)events.GetValue(b, null);
    eventHandlerList .RemoveHandler(eventValue, eventHandlerList [eventValue]);
    MessageBox.Show("Test");
};

但我想从vgridcontrols CellValueChanged事件中删除事件处理程序。我需要为以下“EventClick”撰写什么?

FieldInfo eventclick = typeof(Control).GetField(
    "EventClick",
    BindingFlags.Static | BindingFlags.NonPublic);

2 个答案:

答案 0 :(得分:4)

您不能可靠地从事件中删除事件处理程序,除非您已经拥有一个“平等”委托,您可以正常方式使用-=

使用反射和黑客攻击字段明显违反了封装使您的代码非常脆弱。我会强烈建议不要这样做。

“vgridcontrols”(DataGridView?)你的意思并不清楚,但是你提出的任何解决方案都必然是特定于实现的 - 并且这个实现可以很容易地改变它的下一个版本

相反,花些时间来设计一个你根本不需要删除事件处理程序的设计,或者保持对处理程序的引用并以正常方式删除它。

答案 1 :(得分:0)

这是VB.NET,但您可以轻松地将其修改为C#。这就是你想要的:

'Remove the handler from the cell value changed
Dim gv As DataGridView = Me.equipmentGridView
Dim fInf As FieldInfo = GetType(DataGridView).GetField("EVENT_DATAGRIDVIEWCELLVALUECHANGED", BindingFlags.Static Or BindingFlags.NonPublic)
Dim del As Object = fInf.GetValue(gv)
Dim pInf As PropertyInfo = gv.GetType().GetProperty("Events", BindingFlags.NonPublic Or BindingFlags.Instance)
Dim evList As EventHandlerList = pInf.GetValue(gv, Nothing)
evList.RemoveHandler(del, evList(del))
相关问题