我已经实现了这个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");
}
}
我从不停止引用该方法的所有者,因此我不知道它为什么不起作用,委托的行为是否不同?
答案 0 :(得分:3)
但是&#34; eventreceiver&#34;由方法实例拥有
对不起,但你有倒退了。 &#34; eventReceiver&#34;是要添加到MouseAction事件的委托实例。该委托实例保留对目标对象和MethodInfo的引用,而不是相反。除了WeakReference之外,没有代码保留对委托实例的引用,当然还有设计不足以使对象保持活动状态。
答案 1 :(得分:1)
根据你的回答,我能够修复Weakeventhandler:
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;
}
}
我正在构建一个基于组件的系统,其中Object的组件有时需要与例如鼠标事件进行交互,我不希望为每个从世界中删除的对象取消注册每个组件。