【问题标题】:how to detect event handler and released it?如何检测事件处理程序并释放它?
【发布时间】:2012-10-01 15:00:11
【问题描述】:

假设我有一个类说一个视图模式类 mvvm。然后有一些为此 vm 创建的事件处理程序。那么它可以被许多其他不同情况的人使用。

所以如果我有一个 myvm 的实例,我想检测是否有任何事件处理程序连接并想释放它以解决内存问题。

用myvm做这个的通用方法是什么,例如我可能没有myvm的源代码?

【问题讨论】:

  • 你要发布什么,事件处理程序还是 myvm?

标签: c# events event-handling event-hooking


【解决方案1】:

事件的设计使得声明它们的类之外的代码无法访问底层委托。例如,根据C# Language specification(强调我的)中的“10.8 事件”部分:

在 x += y 或 x -= y 形式的运算中,当 x 是一个事件并且 引用发生在包含 x 的声明,操作结果的类型为 void(如 与具有 x 的类型相反,x 的值在 任务)。 此规则禁止外部代码间接 检查事件的底层委托。

因此,在课堂之外找出订阅了事件的内容可能充其量只是一种“变通方法”。

如果您有权访问包含该事件的类的源并且想要跟踪连接到 event 的委托,请在事件定义中实现 addremove 关键字以及 manually keep track of them in a Dictionary .

【讨论】:

    【解决方案2】:

    如果我理解正确的话。 这个类封装了未知的 myvm 类,我用 SocketAsyncEventArgs 来说明,因为显然我们没有 SocketAsyncEventArgs 类的源代码。

    我包装了 SocketAsyncEventArgs 类的 Completed 事件。当该事件被触发时,_instance_Completed 将被触发,然后 _myvm 事件将被触发。所以我们需要做的是订阅/取消订阅 _myvm 事件。

    然后我留下一个事件供人们订阅/取消订阅 _myvm 事件,作为订阅/取消订阅,代表被存储到一个列表中,因此您可以清除 通过调用 ClearEvents() 方法。

    希望它会有所帮助。

        public class WrapperClass
        {
            private EventHandler<SocketAsyncEventArgs> _myEvent;
            private SocketAsyncEventArgs _myvm;
            private List<Delegate> delegates;
    
            public WrapperClass()
            {
                delegates = new List<Delegate>();
            }
    
            public void SetInstance(SocketAsyncEventArgs myvm)
            {
                _myvm = myvm;
                _myvm.Completed += new EventHandler<SocketAsyncEventArgs>(_instance_Completed);
            }
    
            private void _instance_Completed(object sender, SocketAsyncEventArgs e)
            {
                if (_myEvent != null)
                {
                    _myEvent(sender, e);
                }
            }
    
            public event EventHandler<SocketAsyncEventArgs> myEvent
            {
                add
                {
                    delegates.Add(value);
                    _myEvent = (EventHandler<SocketAsyncEventArgs>)Delegate.Combine(_myEvent, value);
                }
                remove
                {
                    delegates.Remove(value);
                    _myEvent = (EventHandler<SocketAsyncEventArgs>)Delegate.Remove(_myEvent, value);
                }
            }
    
            public void ClearEvents()
            {
                foreach (var d in delegates)
                {
                _myEvent = (EventHandler<SocketAsyncEventArgs>)Delegate.Remove(_myEvent, d);
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-18
      相关资源
      最近更新 更多