c# 通过反射从 BackgroundWorker.DoWork 中删除所有事件处理程序
c# remove all event handler from BackgroundWorker.DoWork by Reflection
我得到了帮助 link -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();
}
我强烈建议不要编写这样的代码。一个设计良好的实现应该不需要任意删除订阅任何 class 的任何事件的所有处理程序,包括 DoWork
或 BackgroundWorker
的其他事件。唯一应该删除处理程序的代码与添加处理程序的代码相同,并且该代码知道它添加了什么处理程序,因此可以直接删除它。
就是说,假设您发布的代码是在继承了 BackgroundWorker
class 的 class 中找到的,它对您不起作用的唯一原因是您尝试使用从 GetField("doWorkKey", ...)
调用返回的 FieldInfo
对象作为事件处理程序的实际键,实际上您应该调用该对象的 GetValue()
方法来获取实际键值。
正确的代码如下所示:
FieldInfo keyField = typeof(BackgroundWorker)
.GetField("doWorkKey", BindingFlags.NonPublic | BindingFlags.Static);
object key = keyField.GetValue(bw);
如果您发布的代码 不是 在继承 BackgroundWorker
class 的 class 中(或者,即使它只是它不是您要修改的 BackgroundWorker
对象),那么您就会遇到第二个问题。您还需要在此处调用 GetValue()
方法时提供正确的 BackgroundWorker
实例:
EventHandlerList events = (EventHandlerList)typeof(Component)
.GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(this, null);
也就是说,不是将 this
传递给 GetValue()
方法,而是需要将引用传递给您尝试修改的实际 BackgroundWorker
对象。
我得到了帮助 link -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();
}
我强烈建议不要编写这样的代码。一个设计良好的实现应该不需要任意删除订阅任何 class 的任何事件的所有处理程序,包括 DoWork
或 BackgroundWorker
的其他事件。唯一应该删除处理程序的代码与添加处理程序的代码相同,并且该代码知道它添加了什么处理程序,因此可以直接删除它。
就是说,假设您发布的代码是在继承了 BackgroundWorker
class 的 class 中找到的,它对您不起作用的唯一原因是您尝试使用从 GetField("doWorkKey", ...)
调用返回的 FieldInfo
对象作为事件处理程序的实际键,实际上您应该调用该对象的 GetValue()
方法来获取实际键值。
正确的代码如下所示:
FieldInfo keyField = typeof(BackgroundWorker)
.GetField("doWorkKey", BindingFlags.NonPublic | BindingFlags.Static);
object key = keyField.GetValue(bw);
如果您发布的代码 不是 在继承 BackgroundWorker
class 的 class 中(或者,即使它只是它不是您要修改的 BackgroundWorker
对象),那么您就会遇到第二个问题。您还需要在此处调用 GetValue()
方法时提供正确的 BackgroundWorker
实例:
EventHandlerList events = (EventHandlerList)typeof(Component)
.GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(this, null);
也就是说,不是将 this
传递给 GetValue()
方法,而是需要将引用传递给您尝试修改的实际 BackgroundWorker
对象。