/MishraReader.Entities/Tools/WeakEventHandler.cs
C# | 285 lines | 157 code | 48 blank | 80 comment | 29 complexity | 5b89d10c402bc1bbda9ac57bef6c9a15 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Diagnostics.Contracts;
- using System.Linq;
- using System.Text;
- using System.Reflection;
- using System.ComponentModel;
- namespace MishraReader
- {
- // The code in this file is from Dustin Campbell's blog at
- // http://diditwith.net/PermaLink,guid,aacdb8ae-7baa-4423-a953-c18c1c7940ab.aspx
- /// <summary>
- /// </summary>
- /// <typeparam name="E"> </typeparam>
- /// <param name="eventHandler"> </param>
- public delegate void UnregisterEventHandler<E>(EventHandler<E> eventHandler) where E : EventArgs;
- /// <summary>
- /// </summary>
- /// <param name="eventHandler"> </param>
- public delegate void UnregisterPropertyChangedEventHandler(PropertyChangedEventHandler eventHandler);
- /// <summary>
- /// </summary>
- /// <typeparam name="E"> </typeparam>
- internal interface IWeakEventHandler<E> where E : EventArgs
- {
- EventHandler<E> Handler { get; }
- WeakReference Target { get; }
- }
- /// <summary>
- /// </summary>
- /// <typeparam name="E"> </typeparam>
- internal interface IWeakPropertyChangedEventHandler
- {
- PropertyChangedEventHandler Handler { get; }
- WeakReference Target { get; }
- }
- /// <summary>
- /// Weak Event Handler, taken from: http://diditwith.net/PermaLink,guid,aacdb8ae-7baa-4423-a953-c18c1c7940ab.aspx
- /// </summary>
- /// <typeparam name="T"> </typeparam>
- /// <typeparam name="E"> </typeparam>
- internal class WeakEventHandler<T, E> : IWeakEventHandler<E>
- where T : class
- where E : EventArgs
- {
- private readonly EventHandler<E> m_Handler;
- private readonly OpenEventHandler m_OpenHandler;
- private readonly WeakReference m_TargetRef;
- private UnregisterEventHandler<E> m_Unregister;
- /// <summary>
- /// </summary>
- /// <param name="eventHandler"> </param>
- /// <param name="unregister"> </param>
- public WeakEventHandler(EventHandler<E> eventHandler, UnregisterEventHandler<E> unregister)
- {
- m_TargetRef = new WeakReference(eventHandler.Target);
- var mi = eventHandler.GetMethodInfo();
- m_OpenHandler = (OpenEventHandler)mi.CreateDelegate(typeof(OpenEventHandler), null);
- m_Handler = Invoke;
- m_Unregister = unregister;
- }
- /// <summary>
- /// </summary>
- public EventHandler<E> Handler
- {
- get { return m_Handler; }
- }
- /// <summary>
- /// </summary>
- public WeakReference Target
- {
- get { return m_TargetRef; }
- }
- /// <summary>
- /// </summary>
- /// <param name="sender"> </param>
- /// <param name="e"> </param>
- public void Invoke(object sender, E e)
- {
- var target = (T)m_TargetRef.Target;
- if (!ReferenceEquals(target, null))
- m_OpenHandler.Invoke(target, sender, e);
- else if (m_Unregister != null)
- {
- m_Unregister(m_Handler);
- m_Unregister = null;
- }
- }
- /// <summary>
- /// </summary>
- /// <param name="weh"> </param>
- /// <returns> </returns>
- public static implicit operator EventHandler<E>(WeakEventHandler<T, E> weh)
- {
- return weh.m_Handler;
- }
- private delegate void OpenEventHandler(T @this, object sender, E e);
- }
- /// <summary>
- /// Weak Event Handler, taken from: http://diditwith.net/PermaLink,guid,aacdb8ae-7baa-4423-a953-c18c1c7940ab.aspx
- /// </summary>
- /// <typeparam name="T"> </typeparam>
- internal class WeakPropertyChangedEventHandler<T> : IWeakPropertyChangedEventHandler
- where T : class
- {
- private readonly PropertyChangedEventHandler m_Handler;
- private readonly OpenEventHandler m_OpenHandler;
- private readonly WeakReference m_TargetRef;
- private UnregisterPropertyChangedEventHandler m_Unregister;
- /// <summary>
- /// </summary>
- /// <param name="eventHandler"> </param>
- /// <param name="unregister"> </param>
- public WeakPropertyChangedEventHandler(PropertyChangedEventHandler eventHandler, UnregisterPropertyChangedEventHandler unregister)
- {
- m_TargetRef = new WeakReference(eventHandler.Target);
- var mi = eventHandler.GetMethodInfo();
- m_OpenHandler = (OpenEventHandler)mi.CreateDelegate(typeof(OpenEventHandler), null);
- m_Handler = Invoke;
- m_Unregister = unregister;
- }
- /// <summary>
- /// </summary>
- public PropertyChangedEventHandler Handler
- {
- get { return m_Handler; }
- }
- /// <summary>
- /// </summary>
- public WeakReference Target
- {
- get { return m_TargetRef; }
- }
- /// <summary>
- /// </summary>
- /// <param name="sender"> </param>
- /// <param name="e"> </param>
- public void Invoke(object sender, PropertyChangedEventArgs e)
- {
- var target = (T)m_TargetRef.Target;
- if (!ReferenceEquals(target, null))
- m_OpenHandler.Invoke(target, sender, e);
- else if (m_Unregister != null)
- {
- m_Unregister(m_Handler);
- m_Unregister = null;
- }
- }
- /// <summary>
- /// </summary>
- /// <param name="weh"> </param>
- /// <returns> </returns>
- public static implicit operator PropertyChangedEventHandler(WeakPropertyChangedEventHandler<T> weh)
- {
- return weh.m_Handler;
- }
- private delegate void OpenEventHandler(T @this, object sender, PropertyChangedEventArgs e);
- }
- /// <summary>
- /// </summary>
- public static class EventHandlerUtils
- {
- /// <summary>
- /// </summary>
- /// <typeparam name="E"> </typeparam>
- /// <param name="eventHandler"> </param>
- /// <param name="unregister"> </param>
- /// <returns> </returns>
- public static EventHandler<E> MakeWeak<E>(this EventHandler<E> eventHandler, UnregisterEventHandler<E> unregister) where E : EventArgs
- {
- Contract.Requires<ArgumentNullException>(eventHandler != null, "eventHandler");
- Contract.Requires<ArgumentException>(!eventHandler.GetMethodInfo().IsStatic && eventHandler.Target != null, "Only instance methods are supported.");
- var method = eventHandler.GetMethodInfo();
- // check to see if we're already weak
- if (method.DeclaringType.GetTypeInfo().IsGenericType && method.DeclaringType.GetGenericTypeDefinition() == typeof(WeakEventHandler<,>))
- {
- return eventHandler;
- }
- var wehType = typeof(WeakEventHandler<,>).MakeGenericType(method.DeclaringType, typeof(E));
- var wehConstructor =wehType.GetTypeInfo().DeclaredConstructors.First();
- var weh = (IWeakEventHandler<E>)wehConstructor.Invoke(
- new object[] {eventHandler, unregister});
- return weh.Handler;
- }
- /// <summary>
- /// </summary>
- /// <typeparam name="E"> </typeparam>
- /// <param name="eventHandler"> </param>
- /// <param name="unregister"> </param>
- /// <returns> </returns>
- public static PropertyChangedEventHandler MakeWeak(this PropertyChangedEventHandler eventHandler, UnregisterPropertyChangedEventHandler unregister)
- {
- Contract.Requires<ArgumentNullException>(eventHandler != null, "eventHandler");
- Contract.Requires<ArgumentException>(!eventHandler.GetMethodInfo().IsStatic && eventHandler.Target != null, "Only instance methods are supported.");
- var method = eventHandler.GetMethodInfo();
- // check to see if we're already weak
- if (method.DeclaringType.GetTypeInfo().IsGenericType && method.DeclaringType.GetGenericTypeDefinition() == typeof(WeakPropertyChangedEventHandler<>))
- {
- return eventHandler;
- }
- var wehType = typeof(WeakPropertyChangedEventHandler<>).MakeGenericType(method.DeclaringType);
- var wehConstructor = wehType.GetTypeInfo().DeclaredConstructors.First();
- var weh = (IWeakPropertyChangedEventHandler)wehConstructor.Invoke(
- new object[] { eventHandler, unregister });
- return weh.Handler;
- }
- /// <summary>
- /// </summary>
- /// <typeparam name="E"> </typeparam>
- /// <param name="sourceHandler"> </param>
- /// <param name="value"> </param>
- /// <returns> </returns>
- public static EventHandler<E> Unregister<E>(this EventHandler<E> sourceHandler, EventHandler<E> value) where E : EventArgs
- {
- Contract.Requires<ArgumentNullException>(value != null, "value");
- Contract.Requires<ArgumentException>(!value.GetMethodInfo().IsStatic && value.Target != null, "Only instance methods are supported.");
-
- if (sourceHandler != null)
- {
- // look for the weak event handler in the invocation list
- foreach (EventHandler<E> evt in sourceHandler.GetInvocationList())
- {
- var weh = evt.Target as IWeakEventHandler<E>;
- if (weh != null)
- {
- var target = weh.Target.Target;
- if (!ReferenceEquals(target, null) && ReferenceEquals(target, value.Target))
- {
- return weh.Handler;
- }
- }
- }
- }
- // return the input as the default if we don't find a wrapped event handler
- return value;
- }
- }
- }