Как определить обработчик события и освободить его?
Предположим, у меня есть класс, скажем, класс режима просмотра mvvm. Тогда есть несколько обработчиков событий, созданных для этого vm. тогда это может быть использовано многими другими с другой ситуацией.
Поэтому, если у меня есть экземпляр myvm, я хочу определить, подключен ли какой-либо обработчик событий, и хочу освободить его из-за проблем с памятью.
Какой общий способ сделать это из myvm, например, у меня может не быть исходного кода myvm?
2 ответа
События разработаны таким образом, что код за пределами объявившего их класса не может получить доступ к базовому делегату. Например, в соответствии с разделом "10.8 События" в спецификации языка C# (выделено мое):
В операции вида x += y или x -= y, когда x является событием и ссылка имеет место вне типа, который содержит объявление x, результат операции имеет тип void (в отличие от наличия тип х, со значением х после присваивания). Это правило запрещает внешнему коду косвенно проверять базовый делегат события.
Поэтому выяснение того, что подписано на мероприятие вне класса, может быть, в лучшем случае, "обходным путем".
Если у вас есть доступ к источнику класса, содержащего событие, и вы хотите отслеживать делегатов, подключенных к событию, внедрите ключевое слово add и remove в определении события и вручную отследите их в Словаре.
Если я вас правильно понимаю. Этот класс оборачивает неизвестный класс myvm, для иллюстрации которого я использую SocketAsyncEventArgs, поскольку очевидно, что у нас нет исходного кода для класса SocketAsyncEventArgs.
И я обернул событие Completed класса SocketAsyncEventArgs. Когда это событие инициировано, будет запущено _instance_Completed, а затем будет запущено событие _myvm. Так что нам нужно подписаться на событие _myvm.
Затем я оставляю событие для людей, чтобы подписаться / отписаться от события _myvm, так как при подписке / отписке делегаты сохраняются в List, поэтому вы можете очистить вызов с помощью метода 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);
}
}
}