假设我有一个类,比如viewmode类mvvm。然后为这个vm创建了一些事件处理程序。那么它可以被许多其他情况不同的人使用。
所以,如果我有一个myvm的实例,我想检测是否有任何连接的事件处理程序,并想释放它以解决内存问题。
用myvm做这件事的通用方法是什么?例如,我可能没有myvm的源代码?
事件的设计使得声明它们的类之外的代码无法访问底层委托。例如,根据C#语言规范(强调矿)中的"10.8事件"部分:
在x+=y或x-=y形式的运算中,当x是一个事件并且引用发生在包含x的声明,则操作的结果具有类型void(as与x的类型相反,x的值在分配)此规则禁止外部代码间接检查事件的基础委托
因此,找出类外事件的订阅内容充其量可能是一种"变通方法"。
如果您有权访问包含事件的类的源,并且希望跟踪连接到事件的委托,请在事件定义中实现add和remove关键字,并在Dictionary中手动跟踪它们。
如果我理解正确的话。这个类包装了未知的myvm类,我用SocketAsyncEventArgs来说明它,因为显然我们没有SocketAsync EventArgs类的源代码。
我包装了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);
}
}
}