[C#] 弱委托,支持+=和-=写法
class ClassA { public void Print1() { Console.WriteLine("111"); } public void Print2() { Console.WriteLine("222"); } public void Print3() { Console.WriteLine("333"); } }
private static WeakDelegate<Action> weak; static void Main(string[] args) { Test(); var a = new ClassA(); weak += a.Print2; weak += a.Print3; weak -= a.Print3; GC.Collect(); GC.WaitForPendingFinalizers(); var target = weak.Target; target?.Invoke(); Console.WriteLine("End"); Console.ReadLine(); } private static void Test() { weak += new ClassA().Print1; }
输出:
222
End
class WeakDelegate<T> where T : Delegate { #region Static Method public static WeakDelegate<T> operator +(WeakDelegate<T> weakDelegate, T t) { if (t == null) return weakDelegate; var ret = new WeakDelegate<T>(t); if (weakDelegate != null) ret._tuples.InsertRange(0, weakDelegate._tuples); return ret; } public static WeakDelegate<T> operator -(WeakDelegate<T> weakDelegate, T t) { if (t == null) return weakDelegate; var ret = new WeakDelegate<T>(null); if (weakDelegate != null) { foreach (var tuple in weakDelegate._tuples) { var weak = tuple.Item1; var method = tuple.Item2; if (!method.IsStatic && !weak.IsAlive) continue; if (weak.Target == t.Target && method == t.GetMethodInfo()) continue; ret._tuples.Add(tuple); } } return ret; } #endregion public WeakDelegate(T t) { _delegateType = typeof(T); _tuples = new List<Tuple<WeakReference, MethodInfo>>(); if (t != null) { var weak = new WeakReference(t.Target); var method = t.GetMethodInfo(); _tuples.Add(new Tuple<WeakReference, MethodInfo>(weak, method)); } } public bool IsAlive => _tuples.Any(q => q.Item1.IsAlive); public T Target { get { var delegates = new List<Delegate>(_tuples.Count); foreach (var tuple in _tuples) { var weak = tuple.Item1; var method = tuple.Item2; if (method.IsStatic) delegates.Add(method.CreateDelegate(_delegateType, null)); var target = weak.Target; if (target != null) delegates.Add(method.CreateDelegate(_delegateType, target)); } return delegates.Count == 0 ? null : (T)Delegate.Combine(delegates.ToArray()); } } private List<Tuple<WeakReference, MethodInfo>> _tuples; private Type _delegateType; }