c#通过Reflection从BackgroundWorker.DoWork中删除所有事件处理程序

时间:2017-07-23 12:48:40

标签: c# reflection backgroundworker eventhandler

我通过此链接获得了帮助 - How to remove all event handlers from a control

是的,我成功从控件和表单中删除了所有事件处理程序。

但我在BackgroundWorker中失败了。

这是我的代码。

    void ReadingCompleted()
    {
        //find fields
        List<FieldInfo> liField=typeof(BackgroundWorker).GetFields(BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Public).ToList();

        foreach(FieldInfo field in liField)
        {
            txtbox_log.Text += field.Name + "\r\n";
        }
        //below output list 
        //canCancelWorker
        //workerReportsProgress
        //cancellationPending
        //isRunning
        //asyncOperation
        //threadStart
        //operationCompleted
        //progressReporter
        //doWorkKey
        //runWorkerCompletedKey
        //progressChangedKey

        //remove all eventhandler
        object key = typeof(BackgroundWorker).GetField("doWorkKey", BindingFlags.NonPublic | BindingFlags.Static);

        EventHandlerList events = (EventHandlerList)typeof(Component)
        .GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance)
        .GetValue(this, null);
        events.RemoveHandler(key, events[key]);
        waitForm.Close();
    }

1 个答案:

答案 0 :(得分:0)

强烈建议不要写这样的代码。精心设计的实现不应该随意删除订阅任何类的任何事件的所有处理程序,包括DoWorkBackgroundWorker的其他事件。应该删除处理程序的唯一代码是添加处理程序的相同代码,并且代码知道它添加了什么处理程序,因此可以直接删除它。

也就是说,假设您发布的代码是在继承BackgroundWorker类的类中找到的,那么它对您不起作用的唯一原因是您尝试使用FieldInfo对象你从GetField("doWorkKey", ...)调用回来作为事件处理程序的实际键,实际上你应该调用该对象的GetValue()方法来获取实际的键值。

正确的代码如下所示:

FieldInfo keyField = typeof(BackgroundWorker)
    .GetField("doWorkKey", BindingFlags.NonPublic | BindingFlags.Static);
object key = keyField.GetValue(bw);

如果你发布的代码在继承BackgroundWorker类的类中而不是(或者,即使它是,但它不是你想要的BackgroundWorker对象修改),然后你有第二个问题。在此处调用BackgroundWorker方法时,您还需要提供正确的GetValue()实例:

EventHandlerList events = (EventHandlerList)typeof(Component)
    .GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance)
    .GetValue(this, null);

也就是说,您需要将引用传递给您尝试修改的实际this对象,而不是将GetValue()传递给BackgroundWorker方法。