[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;
}
View Code

 

posted @ 2022-04-26 19:27  孤独成派  阅读(160)  评论(0编辑  收藏  举报