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();
}
}
}