代码之家  ›  专栏  ›  技术社区  ›  Scott Langham

C如何删除和清除所有事件

c#
  •  1
  • Scott Langham  · 技术社区  · 16 年前

    理想情况下,我想要一个类似以下的函数(本例不编译):

        void AddRemoveEvent<TEvent, TArgs>(TEvent e, EventHandler<TArgs> h, bool add)
            where TArgs : System.EventArgs
        {
            if (add)
            {
                e += h;
            }
            else
            {
                e -= h;
            }
        }
    

    然后我可以写函数:

    void AddRemoveEvents(bool add)
    {
        AddRemoveEvent(aMemberControl.Click, OnClick, add);
    }
    

    然后我知道我可以再次调用该函数来删除所有处理程序。我认为这比写作、保持和依靠两个功能保持同步要好:

    void AddEvents(bool add)
    {
       aMemberControl.Click += OnClick;
    }
    
    void RemoveEvents(bool add)
    {
       aMemberControl.Click -= OnClick;
    }
    

    一位同事写了一个方便的类,可以做这种使用反射的事情。它非常有用,但它依赖于作为字符串传入的事件的名称。我在找一个 类型安全 版本。有人知道是否可以写这个吗?

    谢谢。

    我知道我不必到处乱丢东西,因为垃圾收集者应该处理大多数情况。但是,有时一个偶然事件会导致泄漏,所以我发现尝试删除我添加的所有事件,而不是试图与一个试图识别确实导致问题的事件的分析器混淆,这样更安全。

    我看到了这个相关的问题:
    How to remove all event handlers from a control

    2 回复  |  直到 16 年前
        1
  •  3
  •   Jon Skeet    16 年前

    不幸的是,你不能直接这么做。在C中没有直接以安全方式提供的“事件对象”。如果你有 EventInfo 但是你得用名字来表达。例如:

    void AddRemoveEvent(object target, string name, Delegate handler, bool add)
        where TArgs : System.EventArgs
    {
        EventInfo info = target.GetType().GetEvent(name);
        // Error handling left as an exercise for the reader :)
        if (add)
        {
            info.AddEventHandler(target, handler);
        }
        else
        {
            info.RemoveEventHandler(target, handler);
        }
    }
    

    不太好:(

    顺便说一句,我不确定我是否会为这个单一的方法而烦恼——我只是有单独的addEventHandler和removeEventHandler方法。可能有一个常见的方法来获取eventinfo,确保它存在并且是适当的类型等等,但不是用于指示添加/删除的布尔值。

        2
  •  1
  •   flq    16 年前

    使用C 3.5,可以在许多情况下用表达式树替换字符串。有许多示例围绕向inotifyPropertyChanged的PropertyChanged事件传递字符串的需要而浮动。FluentHibernate很好地利用这个特性来表示某种类型属性的行为。

    然后你就可以说“删除”之类的话了( (MyControlType t) => t.Click )使用另一个stackoverflow post中的代码,您可能会在不指定实际方法作为事件处理程序的情况下离开。