Для того, чтобы не тратить время на добавление и отладку кода по своевременной отписке от событий, я разработал вспомогательный метод-расширитель, генерирующий для обычного делегата его «слабую» версию, которая не хранит в себе жёсткую ссылку на объект, а использует механизм слабых ссылок (weak references). Используя «слабую» версию делегата во время подписки на событие, объект-генератор события получит только слабую ссылку на объект-подписчик. Поэтому, даже если потом и не отписаться от события, объект-подписчик не будет удерживаться в памяти объектом-генератором.
Пример
Без использования «слабых» делегатов
//Подписка на событие
publisher.PublisherEvent += subscriber.Handler; //Handler - делегат
//А потом где-то в другом месте отдписка от события (если этого не сделать, то publisher будет удерживать в памяти subscriber)
publisher.PublisherEvent -= subscriber.Handler;
* This source code was highlighted with Source Code Highlighter.
С использованием «слабых»
делегатов
publisher.PublisherEvent += (HandlerType)subscriber.Handler.AsWeak(); //Отписываться от события теперь не обязательно.
* This source code was highlighted with Source Code Highlighter.
Исходный код
public static class WeakDelegateHelper
{
public static Delegate AsWeak(this Delegate del)
{
if (del.Target == null)
return del;
var weakTarget = new WeakReference(del.Target);
ParameterExpression[] args = (from p in del.Method.GetParameters()
select Expression.Parameter(p.ParameterType, p.Name)).ToArray();
LambdaExpression expression = Expression.Lambda
(
del.GetType(),
Expression.Condition(Expression.Property(Expression.Constant(weakTarget), "IsAlive"),
Expression.Call(
Expression.Convert(
Expression.Property(Expression.Constant(weakTarget), "Target"),
del.Target.GetType()), del.Method, args),
Expression.Default(del.Method.ReturnType)
),
args
);
return expression.Compile();
}
}
* This source code was highlighted with Source Code Highlighter.
Комментариев нет:
Отправить комментарий