在.Net 4.0中。有没有办法使用WeakEventManager实现弱事件模式,因此它不需要对客户端代码进行任何更改?
我希望客户使用标准+ =来附加到事件:
myObject.Updated += new EventHandler(OnUpdated);
但是我希望它创建一个弱事件引用。从我发现的documentation我知道我需要在客户端上为IWeakEventListener创建一个实例,并使用它来附加WeakEventManager.AddListener
。此外,我需要在客户端上保留对它的引用,否则它将由GC收集,因为WeakEventManger仅保留对它的弱引用。但这需要更改我想避免的客户端代码。有没有办法通过在事件源对象(myObject)中嵌入该逻辑来实现它?
这是一个.Net 4.0问题。
答案 0 :(得分:0)
我已经提出了这种方法,但它不是很好,因为它是很多代码。可以改进吗?
活动持有者类:
public class GotWeakEvent
{
// Keeps strong references to the IWeakEventListeners until it's
// identified that the handlers are gone (GC collected). The check happens when
// the event is raised or a handler is detached.
// If it's never raised an nothing detaches then it leaks
// the WeakReference objects and the listeners.
private readonly List<Tuple<WeakReference, WeakEventListener>> _listeners = new List<Tuple<WeakReference, WeakEventListener>>();
private event EventHandler InternalMyWeakEvent;
public event EventHandler MyWeakEvent
{
add
{
WeakEventListener l = new WeakEventListener(value);
WeakReference wr = new WeakReference(value);
lock (_listeners)
{
_listeners.Add(new Tuple<WeakReference, WeakEventListener>(wr, l));
}
PrivateManager.AddListener(this, l);
}
remove
{
// remove the reference from the listeners list
lock (_listeners)
{
for (int i = _listeners.Count - 1; i >= 0; i--)
{
var tuple = _listeners[i];
if (!tuple.Item1.IsAlive)
{
_listeners.RemoveAt(i);
}
else if ((EventHandler)tuple.Item1.Target == value)
{
PrivateManager.RemoveListener(this, tuple.Item2);
_listeners.RemoveAt(i);
}
}
}
}
}
protected void RaiseMyWeakEvent()
{
// clear dead references
lock (_listeners)
{
for (int i = _listeners.Count - 1; i >= 0; i--)
{
var tuple = _listeners[i];
if (!tuple.Item1.IsAlive)
{
_listeners.RemoveAt(i);
}
}
}
var handler = InternalMyWeakEvent;
if (handler == null) return;
handler(this, new EventArgs());
}
private class PrivateManager : WeakEventManager
{
private static PrivateManager CurrentManager
{
get
{
var managerType = typeof(PrivateManager);
var manager = GetCurrentManager(managerType) as PrivateManager;
if (manager != null) return manager;
manager = new PrivateManager();
SetCurrentManager(managerType, manager);
return manager;
}
}
public static void AddListener(GotWeakEvent source, IWeakEventListener listener)
{
CurrentManager.ProtectedAddListener(source, listener);
}
public static void RemoveListener(GotWeakEvent source, IWeakEventListener listener)
{
CurrentManager.ProtectedRemoveListener(source, listener);
}
protected override void StartListening(object source)
{
((GotWeakEvent)source).InternalMyWeakEvent += DeliverEvent;
}
protected override void StopListening(object source)
{
((GotWeakEvent)source).InternalMyWeakEvent -= DeliverEvent;
}
}
}
WeakEventListener:
public class WeakEventListener : IWeakEventListener
{
private readonly WeakReference _handlerReference;
public WeakEventListener(EventHandler handler)
{
if (handler == null) throw new ArgumentNullException("handler");
_handlerReference = new WeakReference(handler);
}
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
EventHandler handler = _handlerReference.Target as EventHandler;
if (handler == null) return false;
handler(sender, e);
return true;
}
}
最后客户端代码创建了一个弱事件订阅。
GotWeakEvent source = new GotWeakEvent();
// [....]
// normal usage but it's weak
source.MyWeakEvent += OnMyWeakEvent;
private void OnMyWeakEvent(object sender, EventArgs e)
{
// do the stuff
}