using System;using System.Diagnostics;using System.Windows;namespace MyApp.WeakEvent
{publicclass GenericWeakEventListener<T> : IWeakEventListener, IDisposablewhere T : FrameworkElement
{public GenericWeakEventListener(RoutedEventHandler handler)
{
_handler = handler;
}private RoutedEventHandler _handler;publicbool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{var re = (RoutedEventArgs)e;if (managerType == typeof(GenericWeakEventManager<T>) && (re.RoutedEvent == _e))
{
OnEvent(sender, re);returntrue;
}returnfalse;
}privatebool _isInit = false;publicvoid Init(RoutedEvent e, T t)
{if (_isInit)thrownew InvalidOperationException("create another instance of the listener");
_e = e;
_t = new WeakReference(t);
_isInit = true;
}private RoutedEvent _e;private WeakReference _t;privatevoid OnEvent(object sender, RoutedEventArgs e)
{if (_handler != null)
{
_handler(sender, e);
}
}privatebool _disposed = false;
~GenericWeakEventListener()
{
Dispose(false);#if DEBUG
Debug.WriteLine("GC Deleted: GenericWeakEventListener<"+ typeof(T).Name + ">");#endif
}publicvoid Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}privatevoid Dispose(bool disposing)
{if (!_disposed && disposing && _t.IsAlive)
{
GenericWeakEventManager<T>.RemoveListener(_e, (T)_t.Target, (IWeakEventListener)this);#if DEBUG
Debug.WriteLine("Disposing: GenericWeakEventListener<"+ typeof(T).Name + ">");#endif
}
_handler = null;
_e = null;
_t = null;
_disposed = true;
}
}publicclass GenericWeakEventManager<T> : WeakEventManagerwhere T : FrameworkElement //can also be Control
{private GenericWeakEventManager(RoutedEvent e)
{if (e.OwnerType != typeof(T))thrownew InvalidOperationException("event doesn't exists in T");
_event = e;
}
privatereadonly RoutedEvent _event;publicstaticvoid AddListener(RoutedEvent e, DependencyObject source, GenericWeakEventListener<T> listener)
{
listener.Init(e, (T)source);
AddListener(e, source, (IWeakEventListener)listener);
}publicstaticvoid RemoveListener(RoutedEvent e, DependencyObject source, GenericWeakEventListener<T> listener)
{
listener.Dispose();
}publicstaticvoid AddListener(RoutedEvent e, DependencyObject source, IWeakEventListener listener)
{lock (_lock)
{
GetCurrentManager(e);
AddListener(source, listener);
}
}publicstaticvoid RemoveListener(RoutedEvent e, DependencyObject source, IWeakEventListener listener)
{lock (_lock)
{
GetCurrentManager(e);
RemoveListener(source, listener);
}
}///<summary>/// Add a listener to the given source's event.///</summary>privatestaticvoid AddListener(DependencyObject source, IWeakEventListener listener)
{if (source == null)thrownew ArgumentNullException("source");if (listener == null)thrownew ArgumentNullException("listener");
CurrentManager.ProtectedAddListener(source, listener);
}
///<summary>/// Remove a listener to the given source's event. /// no need to call, only implement the opposite of add, and it will be called automatically when needed///</summary>privatestaticvoid RemoveListener(DependencyObject source, IWeakEventListener listener)
{if (source == null)thrownew ArgumentNullException("source");if (listener == null)thrownew ArgumentNullException("listener");
CurrentManager.ProtectedRemoveListener(source, listener);
}
///<summary>/// Listen to the given source for the event.///</summary>protectedoverridevoid StartListening(object source)
{var fe = source as T;if (fe != null)
fe.AddHandler(_event, (RoutedEventHandler)DeliverEvent);
}///<summary>/// Stop listening to the given source for the event.///</summary>protectedoverridevoid StopListening(object source)
{var fe = source as T;if (fe != null)
fe.RemoveHandler(_event, (RoutedEventHandler)DeliverEvent);
}// get the event manager for the current thread & eventprivatestatic GenericWeakEventManager<T> CurrentManager
{get
{
SetCurrentManager(typeof(GenericWeakEventManager<T>), _mgr);//ensure it's therereturn _mgr;
}set
{
_mgr = value;
SetCurrentManager(typeof(GenericWeakEventManager<T>), _mgr);
}
}privatestatic GenericWeakEventManager<T> _mgr = null;privatestaticreadonlyobject _lock = newobject();privatestatic WeakEventManager GetCurrentManager(RoutedEvent e)
{
Dictionary<RoutedEvent, GenericWeakEventManager<T>> d;
GenericWeakEventManager<T> m;if (_dic.TryGetValue(typeof(T), out d))
{if (!d.TryGetValue(e, out m))
{
m = new GenericWeakEventManager<T>(e);
d.Add(e, m);
}
}else
{
d = new Dictionary<RoutedEvent, GenericWeakEventManager<T>>();
m = new GenericWeakEventManager<T>(e);
d.Add(e, m);
_dic.Add(typeof(T), d);
}
CurrentManager = m;
return m;
}privatestaticreadonly Dictionary<Type, Dictionary<RoutedEvent, GenericWeakEventManager<T>>> _dic = new Dictionary<Type, Dictionary<RoutedEvent, GenericWeakEventManager<T>>>();
}
}