这样事件源source会保持一个事件实例EventInstance的强引用。也因为这样,它们都为null时,才会被GC回收,只要任一方还存活时,另一方即使为null,该方还是存活的。这就造成内存泄露。尤其是在silverlight中,内存泄露是件非常可怕的事。
弱事件模式就是为了解决这问题而存在的。在wpf中有弱事件管理器帮助解决,但可惜在传统.net和silverlight中无。而且多数事件已经被使用,无法重新改写成弱事件源模式的事件,因此只能实现监听方的弱事件。
以下是具体实现及使用方式:
namespace Silverlight { public interface IWeakListener { void Attach(bool once = true); void Detach(); void Clear(); } public interface IWeakEventListener<TSource,TEventArgs> : IWeakListener where TSource : class { void Run(Action<IWeakEventListener<TSource,TEventArgs>,TSource> action); void Raise(object source,TEventArgs eventArgs); } }
namespace Silverlight {
/// <summary> /// 弱事件监听器,事件源和事件对象任一方都能被GC回收. /// 通常用在事件对象上.事件委托必须是两个参数,一般用于标准的事件上. /// </summary> /// <remarks> /// 当事件源或事件对象任一方a被回收但另一方b还存活时,/// 此对象w在事件下一次触发前或b被回收前或调用w.Clear()方法前,不能被GC回收. /// </remarks> /// <typeparam name="TInstance">事件对象</typeparam> /// <typeparam name="TSource">事件源</typeparam> /// <typeparam name="TEventArgs">事件EventArgs</typeparam> public class WeakEventListener<TInstance,TSource,TEventArgs> : IWeakEventListener<TSource,TEventArgs> where TInstance : class where TSource : class { public WeakEventListener(TInstance instance,TSource source) { if (instance == null) throw new ArgumentNullException("instance"); //if (source == null) throw new ArgumentNullException("source"); _weakInstance = new WeakReference(instance); _weakSource = new WeakReference(source); }
public WeakEventListener(TInstance instance,TSource source,Action<WeakEventListener<TInstance,TSource> onAttach,TSource> onDetach,Action<TInstance,object,TEventArgs> onEvent,bool isstatic = true) : this(instance,source) { OnAttach = onAttach; OnDetach = onDetach; setonEvent(onEvent,!isstatic); Attach(false); }
private readonly WeakReference _weakInstance; private readonly WeakReference _weakSource;
private bool set_onEventAction_private = true; private Action<TInstance,TEventArgs> _onEventAction; private Action<WeakEventListener<TInstance,TSource> _onDetachAction; private Action<WeakEventListener<TInstance,TSource> _onAttachAction;
private const string warnOnEventAction = "Action must be static otherwise the event WeakEventListner class does not prevent memory leaks.";
private const string warnOnAction = "Action must be static otherwise the event WeakEventListner cannot guarantee to unregister the handler.";
/// <summary> /// 获取或设置事件触发动作,设置该值时,在此类型中value应为Static,/// 在派生类中重写时value可以不为Static,但要考虑能被GC回收. /// </summary> public virtual Action<TInstance,TEventArgs> OnEvent { get { return _onEventAction; } set { if (set_onEventAction_private && (value == null || !value.Method.Isstatic)) throw new ArgumentException(warnOnEventAction); _onEventAction = value; } }
/// <summary> /// 获取或设置事件移除方式 /// </summary> public Action<WeakEventListener<TInstance,TSource> OnDetach { get { return _onDetachAction; } set { if (value == null || !value.Method.Isstatic) throw new ArgumentException(warnOnAction); _onDetachAction = value; } }
/// <summary> /// 获取或设置事件附加方式 /// </summary> public Action<WeakEventListener<TInstance,TSource> OnAttach { get { return _onAttachAction; } set { if (value == null || !value.Method.Isstatic) throw new ArgumentException(warnOnAction); _onAttachAction = value; } }
/// <summary> /// 事件激发,通常把此方法当成委托附加到事件源. /// 可以手动调用此方法,当作事件触发. /// </summary> public void Raise(object source,TEventArgs eventArgs) { var target = (TInstance) _weakInstance.Target; if (target != null) { if (OnEvent != null) OnEvent(target,source,eventArgs); } else { Clear(); } }
/// <summary> /// 设置事件事件附加或移除方式(可以处理Attach,Detach) /// </summary> /// <param name="action">action可以不是静态</param> public void Run(Action<IWeakEventListener<TSource,TSource> action) { var source = (TSource) _weakSource.Target; if (action != null && source != null) action(this,source); else if (source == null) Clear(); }
/// <summary> /// 事件附加(只能处理OnAttach) /// </summary> /// <param name="once">附加前是否先移除,默认为true</param> public void Attach(bool once = true) { if (once) Detach(); var source = (TSource) _weakSource.Target; if (OnAttach != null && source != null) OnAttach(this,source); else if (source == null) Clear(); }
/// <summary> /// 事件移除(只能处理OnDetach) /// </summary> public void Detach() { clearPrivate(false); }
/// <summary> /// 清理监听器 /// </summary> public void Clear() { clearPrivate(true); }
private void clearPrivate(bool all) { var source = (TSource) _weakSource.Target; if (OnDetach != null && source != null) OnDetach(this,source); if (!all && source != null) return; setonEvent(null); _onAttachAction = null; _onDetachAction = null; }
private void setonEvent(Action<TInstance,TEventArgs> action,bool notcheck = true) { if (notcheck) set_onEventAction_private = false; OnEvent = action; set_onEventAction_private = true; } } }
/*********************************************************************************************** //监听器在代码中位置并无要求 var w = new WeakEventListener<TInstance,EventArgs>(TInstance,source); w.OnEvent += (i,s,eventArgs) => i._event(s,eventArgs); w.OnDetach += (o,s) => s.MyEvent -= o.Raise; w.OnAttach += (o,s) => s.MyEvent += o.Raise; w.Detach(); w.Attach(); ***********************************************************************************************/
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。