1

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

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

从 myvm 中执行此操作的通用方法是什么,例如,我可能没有 myvm 的源代码?

4

2 回答 2

2

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

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

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

如果您有权访问包含该事件的类的源并且您希望跟踪连接到某个事件的委托,请在事件定义中实现addremove 关键字,并在 Dictionary 中手动跟踪它们

于 2012-10-01T15:17:16.120 回答
0

如果我理解正确的话。这个类包装了未知的 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);
            }
        }
    }
于 2012-10-01T16:06:50.580 回答