我需要创建一个 RichTextBox 子类,除了它不订阅 UserPreferenceChanged 之外,它在所有方面都工作相同。此事件导致我的应用程序挂起。我必须使用 RichTextBox,并且无法将其替换为 MultiLine=True 的 TextBox 或其他类似的内容。
这是 System.Windows.Forms.RichTextBox 订阅的地方;
protected override void OnHandleCreated(EventArgs e)
{
...
SystemEvents.UserPreferenceChanged += new UserPreferenceChangedEventHandler(this.UserPreferenceChangedHandler);
}
这是处理程序的签名;
private void UserPreferenceChangedHandler(object o, UserPreferenceChangedEventArgs e)
该处理程序不是虚拟的,因此我无法覆盖它。该处理程序是私有(private)的,因此我无法执行简单的 -= 取消订阅。我已经研究过使用反射来删除处理程序,但我无法让它工作 - 这就是我到目前为止所拥有的;
public partial class MyRichTextBox : RichTextBox
{
...
private void UnsubscribeUserPreferenceChanged()
{
FieldInfo fieldInfo = typeof(SystemEvents).GetField("OnUserPreferenceChangedEvent", BindingFlags.NonPublic | BindingFlags.Static);
// fieldInfo.ToString() = "System.Object.OnUserPreferenceChangedEvent"
object eventObj = fieldInfo.GetValue(this);
// eventInfo.ToString() = "System.Object"
PropertyInfo propInfo = typeof(RichTextBox).GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
// propInfo.ToString() = "System.ComponentModel.EventHandlerList Events"
EventHandlerList list = (EventHandlerList)propInfo.GetValue(this, null);
// list.ToString() = "System.ComponentModel.EventHandlerList"
...
现在我可以打电话了;
list.RemoveHandler(eventObj, list[eventObj]);
并且不会有异常(exception),但我相信它会默默地失败,因为如果我尝试这样访问委托(delegate);
list[eventObj].ToString()
我收到 NullReferenceException,因为 EventHandlerList 中没有这样的对象键。我在 MyTextBox 变得可见后调用 UnsubscribeUserPreferenceChanged(),因此处理程序应该在列表中,因为它是在 OnHandleCreated 中为 RichTextBox 添加的。
有人知道如何取消订阅与父类(super class)中的私有(private)事件处理程序 Hook 的 SystemEvent 吗?
最佳答案
一旦您知道方法名称,由于以下方便的 CreateDelegate
,这很容易过载:
public static Delegate CreateDelegate(
Type type,
object target,
string method
)
所以有问题的代码可能是这样的:
private void UnsubscribeUserPreferenceChanged()
{
var handler = (UserPreferenceChangedEventHandler)Delegate.CreateDelegate(
typeof(UserPreferenceChangedEventHandler), this, "UserPreferenceChangedHandler");
SystemEvents.UserPreferenceChanged -= handler;
}
关于c# - 我可以使用反射取消订阅系统事件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39980299/