using System; using System.Reflection; using Developpez.Dotnet.Reflection; namespace Developpez.Dotnet { /// /// Permet de référencer faiblement un delegate /// /// Type de delegate public class WeakDelegate : IEquatable { private readonly WeakReference _targetReference; private readonly MethodInfo _method; /// /// Initialise une nouvelle instance de avec le delegate spécifié. /// /// Le delegate pour lequel créer une référence faible public WeakDelegate(Delegate realDelegate) { _targetReference = realDelegate.Target != null ? new WeakReference(realDelegate.Target) : null; #if NETFX_CORE _method = realDelegate.GetMethodInfo(); #else _method = realDelegate.Method; #endif } /// /// Obtient le delegate englobé par cette référence faible /// /// Le delegate englobé par cette référence faible public TDelegate GetDelegate() { return (TDelegate)(object)GetDelegateInternal(); } #if NETFX_CORE private Delegate GetDelegateInternal() { if (_targetReference != null) { object target = _targetReference.Target; if (target != null) return _method.CreateDelegate(typeof(TDelegate), target); throw new InvalidOperationException("The delegate target has been collected"); } return _method.CreateDelegate(typeof(TDelegate)); } #else private Delegate GetDelegateInternal() { if (_targetReference != null) { object target = _targetReference.Target; if (target != null) return Delegate.CreateDelegate(typeof(TDelegate), target, _method); throw new InvalidOperationException("The delegate target has been collected"); } return Delegate.CreateDelegate(typeof(TDelegate), _method); } #endif /// /// Indique si le delegate est encore actif (true) ou s'il a été collecté (false) /// public bool IsAlive { get { return _targetReference == null || _targetReference.IsAlive; } } #region IEquatable Members /// /// Indique si cette instance est équivalente au delegate spécifié /// /// Le delegate avec lequel comparer cette instance /// true si cette instance est équivalente au delegate spécifié, sinon false public bool Equals(TDelegate other) { Delegate d = (Delegate)(object)other; return d != null && d.Target == _targetReference.Target #if NETFX_CORE && d.GetMethodInfo().Equals(_method); #else && d.Method.Equals(_method); #endif } #endregion /// /// Invoke le delegate avec les arguments spécifiés /// /// Arguments à passer au delegate /// La valeur de retour du delegate public object Invoke(params object[] args) { object target = _targetReference.Target; if (target != null) return _method.Invoke(_targetReference.Target, args); return _method.ReturnType.GetDefaultValue(); } } }