Я не думаю, что этот шаблон делает то, что вы ожидаете. Вы пытаетесь предотвратить удержание события ссылки на текущий объект, чтобы предотвратить утечки памяти? Лямбда-выражение будет фиксировать значение this
, чтобы оценить ProcessEvent
(при условии, что ProcessEvent
- это метод экземпляра), поэтому утечка все равно останется Этот код такой же, как и для SomeEvent += (sender, e) => ProcessEvent();
.
Возможно, вы пытаетесь сделать что-то более похожее на это (что тоже не то, что вы хотите):
var reference = new WeakReference((Action)ProcessEvent);
SomeEvent += (sender, e) => ((Action)reference.Target)();
Теперь лямбда-выражение будет захватывать WeakReference, поэтому у вас не будет сильной ссылки на this
. К сожалению, ничто иное не ссылается на делегат, созданный из ProcessEvent, поэтому он будет удален на следующем GC, даже если this
еще жив. (Это также не проверяет, является ли цель недействительной).
Вы можете попробовать что-то вроде этого:
public EventHandler MakeWeakHandler(Action action, Action<EventHandler> remove)
{
var reference = new WeakReference(action.Target);
var method = action.Method;
EventHandler handler = null;
handler = delegate(object sender, EventArgs e)
{
var target = reference.Target;
if (target != null)
{
method.Invoke(target, null);
}
else
{
remove(handler);
}
};
return handler;
}
, а затем используйте его так:
SomeEvent += MakeWeakHandler(ProcessEvent, h => SomeEvent -= h);
Это сохранит слабую ссылку на получатель ProcessEvent и автоматически удалит обработчик события из события после его сбора, что должно предотвратить утечки памяти, если событие вызывается регулярно.