WeakReference too weak?

本文关键字:weak too WeakReference | 更新日期: 2023-09-27 18:26:54

我已经实现了这个WeakEvent委托,但由于某种原因,它只工作几秒钟,之后它就停止工作了:

public class WeakEventHandler<TE>  where TE : EventArgs
{
    private readonly Action<WeakEventHandler<TE>> _unsubscriber;
    private readonly WeakReference<EventHandler<TE>> _targetRef;
    private readonly EventHandler<TE> _handler;

    public WeakEventHandler(EventHandler<TE> eventReceiver, Action<WeakEventHandler<TE>> unsubscriber)
    {
        _unsubscriber = unsubscriber;
        _targetRef = new WeakReference<EventHandler<TE>>(eventReceiver);
        _handler = Invoke;
    }
    public void Invoke(object sender, TE e)
    {
        EventHandler<TE> method;
        if (_targetRef.TryGetTarget(out method))
        {
            method(sender, e);
        }
        else
        {
            _unsubscriber(this);
        }
    }
    public static implicit operator EventHandler<TE>(WeakEventHandler<TE> weh)
    {
        return weh._handler;
    }
}
public static class EventHandlerUtils
{
    public static EventHandler<TE> MakeWeak<TE>(this EventHandler<TE> eventReceiver, Action<WeakEventHandler<TE>> unsubscriber) where TE : EventArgs
    {
        return new WeakEventHandler<TE>(eventReceiver, unsubscriber);
    }
}

用法:

    private EventHandler<MouseInteractionArgs> _mouseInteractionDelegate;
    public event EventHandler<MouseInteractionArgs> MouseAction
    {
        add
        {
            _mouseInteractionDelegate += value.MakeWeak(handler => _mouseInteractionDelegate -= handler );
        }
        remove
        {
            throw new InvalidOperationException("This is a weak Event, dont worry about unsubscribing");
        }
    }

我从未停止引用该方法的所有者,所以我不知道为什么它不起作用,代理的行为是否不同?

WeakReference too weak?

但是"事件接收器"由方法的实例所有

对不起,你倒过来了。"eventReceiver"是要添加到MouseAction事件中的委托实例。该委托实例保留了对目标对象和MethodInfo的引用,而不是相反。除了WeakReference之外,没有任何代码可以保留对委托实例的引用,当然,从设计上讲,这不足以保持对象的活力。

根据您的回答,我能够修复Weakeeventhandler:

public class WeakEventHandler<TE> where TE : EventArgs
{
    private delegate void OpenEventHandler(object target, object sender, TE e);
    private readonly WeakReference _targetRef;
    private readonly OpenEventHandler _openHandler;
    private readonly Action<WeakEventHandler<TE>> _unsubscriber;
    private readonly EventHandler<TE> _handler;

    public WeakEventHandler(EventHandler<TE> subscriber, Action<WeakEventHandler<TE>> unsubscriber)
    {
        _unsubscriber = unsubscriber;
        _targetRef = new WeakReference(subscriber.Target);
        _handler = Invoke;

        var target = Expression.Parameter(typeof (object), "target");
        var sender = Expression.Parameter(typeof(object), "sender");
        var args = Expression.Parameter(typeof (TE), "args");
        _openHandler =
            Expression.Lambda<OpenEventHandler>(
                Expression.Call(Expression.Convert(target, subscriber.Target.GetType()), subscriber.Method, sender,
                    args),target,sender,args).Compile();
    }
    public void Invoke(object sender, TE e)
    {
        var t = _targetRef.Target;
        if (t != null)
        {
            _openHandler(t, sender, e);
        }
        else
        {
            _unsubscriber(this);
        }
    }
    public static implicit operator EventHandler<TE>(WeakEventHandler<TE> weh)
    {
        return weh._handler;
    }
}

我正在构建一个基于组件的系统,对象的组件有时需要与例如鼠标事件进行交互,我不想为我从世界上删除的每个对象注销每个组件。