trim HttpHeaders
石头 编写于 2024-06-22 08:55:23
X
using System;
using System.Reflection;
using System.Threading;
using NewLife.Reflection;

namespace NewLife
{
    /// <summary>弱引用事件</summary>
    /// <remarks>
    /// 很多绑定事件的场合,并不适合取消绑定,这就造成了事件资源无法得到回收。
    /// 更加麻烦的是,事件本身除了包含事件处理方法外,还会包含目标对象,也就导致目标对象无法得到释放。
    /// 弱引用事件的原理是把目标对象与事件处理方法分拆开来,使用弱引用来引用目标对象,保证目标对象能够得到有效的释放。
    /// 触发弱引用事件时,首先判断目标对象是否可用,因为其可能已经被GC回收,然后再通过快速访问方法调用事件处理方法。
    /// 也许有人会问,如果目标对象不可用怎么办?岂不是无法执行事件处理方法了?
    /// 我们换一个角度来看,既然目标对象都已经不存在了,它绑定的事件自然也就无需过问了!
    /// </remarks>
    /// <typeparam name="TEventArgs"></typeparam>
    public class WeakEventHandler<TEventArgs> where TEventArgs : EventArgs
    {
        #region 属性
        /// <summary>目标对象。弱引用,使得调用方对象可以被GC回收</summary>
        WeakReference Target;

        /// <summary>委托方法</summary>
        MethodBase Method;

        /// <summary>经过包装的新的委托</summary>
        EventHandler<TEventArgs> Handler;

        /// <summary>取消注册的委托</summary>
        Action<EventHandler<TEventArgs>> UnHandler;

        /// <summary>是否只使用一次,如果只使用一次,执行委托后马上取消注册</summary>
        Boolean Once;
        #endregion

        /// <summary>使用事件处理器、取消注册回调、是否一次性事件来初始化</summary>
        /// <param name="handler"></param>
        /// <param name="unHandler"></param>
        /// <param name="once"></param>
        public WeakEventHandler(EventHandler<TEventArgs> handler, Action<EventHandler<TEventArgs>> unHandler, Boolean once)
        {
            if (handler.Target != null)
            {
                Target = new WeakReference(handler.Target);
            }
            else
            {
                if (!handler.Method.IsStatic) throw new InvalidOperationException("非法事件,没有指定类实例且不是静态方法!");
            }

            //Method = MethodInfoEx.Create(handler.Method);
            Method = handler.Method;
            Handler = Invoke;
            UnHandler = unHandler;
            Once = once;
        }

        /// <summary>调用委托</summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Invoke(Object sender, TEventArgs e)
        {
            //if (!Target.IsAlive) return;
            // Keep in mind that,不要用上面的写法,因为判断可能通过,但是接着就被GC回收了,如果判断Target,则会增加引用
            Object target = null;
            if (Target == null)
            {
                if (Method.IsStatic) target.Invoke(Method, new Object[] { sender, e });
            }
            else
            {
                target = Target.Target;
                if (target != null) target.Invoke(Method, new Object[] { sender, e });
            }

            // 调用方已被回收,或者该事件只使用一次,则取消注册
            if ((Target != null && target == null || Once) && UnHandler != null)
            {
                UnHandler(Handler);
                UnHandler = null;
            }
        }

        /// <summary>把弱引用事件处理器转换为普通事件处理器</summary>
        /// <param name="handler"></param>
        /// <returns></returns>
        public static implicit operator EventHandler<TEventArgs>(WeakEventHandler<TEventArgs> handler)
        {
            return handler == null ? null : handler.Handler;
        }

        /// <summary>绑定</summary>
        /// <param name="handler"></param>
        public void Combine(ref EventHandler<TEventArgs> handler)
        {
            //handler += Handler;

            EventHandler<TEventArgs> oldHandler;
            EventHandler<TEventArgs> newHandler = null;
            do
            {
                oldHandler = handler;
                if (oldHandler == null) return;

                newHandler = Delegate.Combine(oldHandler, Handler) as EventHandler<TEventArgs>;

            } while (Interlocked.CompareExchange<EventHandler<TEventArgs>>(ref handler, newHandler, oldHandler) != oldHandler);
        }

        /// <summary>移除</summary>
        /// <param name="handler"></param>
        /// <param name="value">数值</param>
        public static void Remove(ref EventHandler<TEventArgs> handler, EventHandler<TEventArgs> value)
        {
            //handler -= value;

            EventHandler<TEventArgs> oldHandler;
            EventHandler<TEventArgs> newHandler = null;
            do
            {
                oldHandler = handler;
                if (oldHandler == null) return;

                var ds = oldHandler.GetInvocationList();
                if (ds == null || ds.Length < 1) return;

                for (int i = 0; i < ds.Length; i++)
                {
                    var wh = ds[i].Target as WeakEventHandler<TEventArgs>;
                    if (wh == null || wh.Method != value.Method) continue;

                    // 判断对象
                    if (wh.Target == null)
                    {
                        if (value.Target != null) continue;
                    }
                    else
                    {
                        if (value.Target == null || wh.Target.Target != value.Target) continue;
                    }

                    // 移除
                    newHandler = Delegate.Remove(oldHandler, ds[i]) as EventHandler<TEventArgs>;
                }
            } while (Interlocked.CompareExchange<EventHandler<TEventArgs>>(ref handler, newHandler, oldHandler) != oldHandler);
        }
    }
}