当我在派生类中时,如何“取消绑定”附加到基类中的事件的事件处理程序?

时间:2009-04-03 14:35:24

标签: c# event-handling

我曾经遇到过一种情况,我不得不在我的某个派生类中覆盖事件处理程序。遗憾的是,我不能“覆盖”它,因为实现逻辑严格地绑定到基类中的特定方法实现。

我的自然想法是首先从事件中“取消绑定”原始事件处理程序,然后绑定我自己的全新方法。所以我尝试使用“ - =”运算符,如:

myObject.SomeEvent -= new EventHandler (BaseClass.SomeEventHandler)

此时编译器抱怨它无法访问私有方法SomeEventHandler。由于基类是库的一部分,我并不是真的想要修改它的实现(尽管只是将它看作是“私有”变成“受保护”);

将事件处理程序附加到事件非常简单。为什么摆脱一个这么难?

为什么我想要它?因为基本实现存在一些问题(只是没有处理我们的特定情况)所以我想重新定义它。但即使在我附加了我的事件处理程序之后,基本实现仍然会被执行。由于它正在进行某种重定向,因为重定向后服务器上的请求处理被破坏,我自己的实现永远不会运行。

无论如何都要从库中删除基类中的事件处理程序而不修改它的实现吗?

1 个答案:

答案 0 :(得分:5)

如果你的代码可以正式看到处理程序, 就可以轻松摆脱处理程序。如果绝对必要,可以使用反射取消订阅以获取代理,但这很麻烦。这将是 lot 更清洁,并且更安全:a避免要求,或b:更改代码以生成处理程序protected


反思方法(自担风险使用);取消注释Bar.ctor()中的块以查看更改。

using System;
class Foo
{
    public event EventHandler SomeEvent;
    public Foo()
    {
        SomeEvent += SecretHandler; // a bad idea, anyway
                                    //(self-subscribed events....)
    }
    protected virtual void OnSomeEvent()
    {
        EventHandler handler = SomeEvent;
        if (handler != null) handler(this, EventArgs.Empty);
    }
    private void SecretHandler(object sender, EventArgs args)
    {
        Console.WriteLine("suscribed");
    }
}
class Bar : Foo
{
    public Bar()
    {
        /*
        MethodInfo method = typeof(Foo).GetMethod("SecretHandler",
            BindingFlags.NonPublic | BindingFlags.Instance);
        EventHandler handler = (EventHandler)Delegate.CreateDelegate(
            typeof(EventHandler), this, method);
        SomeEvent -= handler;
         */
    }
    public void Test()
    {
        OnSomeEvent();
    }
}
static class Program
{
    static void Main()
    {
        Bar bar = new Bar();
        bar.Test();
    }
}