C# 有关控件、自定义类事件中的委托链的获取、移除操作

 

直接来代码吧,这样干脆直接,也不耽误我午休了。一切尽在源码中。

public class ControlEventTool
{

    /// <summary>
    /// 移除控件的某类事件, 如Click事件
    /// 2018.3.21
    /// </summary>
    public static void DemoRemoveControlEvents(System.Windows.Forms.Button btn, string eventName = "Click")
    {
        // 检索按钮的事件,这里单击事件的名字是EventClick,要注意的
        Delegate[] invokeList = GetObjectEventList(btn, "Event" + eventName);
        if (invokeList != null)
        {
            foreach (Delegate del in invokeList)
            {
                // 我已经测试,事件被全部取消了,没有问题。
                typeof(System.Windows.Forms.Button).GetEvent(eventName).RemoveEventHandler(btn, del);
            }
        }
    }

    /// <summary>
    /// 获取控件指定事件的委托列表  
    /// </summary>
    /// <param name="p_Control">对象</param>
    /// <param name="p_EventName">事件名 EventClick、EventDoubleClick、EventMouseMove</param>
    /// <returns>委托列</returns>
    public static Delegate[] GetObjectEventList(Control p_object, string p_EventName)
    {
        PropertyInfo _PropertyInfo;
        FieldInfo fieldInfo;
        EventHandlerList evList;
        Delegate d;
        object _EventList;

        _PropertyInfo = p_object.GetType().GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
        if (_PropertyInfo == null) return null;
        _EventList = _PropertyInfo.GetValue(p_object, null);

        if (_EventList == null || !(_EventList is EventHandlerList)) return null;
        evList = (EventHandlerList)_EventList;
        fieldInfo = (typeof(Control)).GetField(p_EventName, BindingFlags.Static | BindingFlags.NonPublic);
        if (fieldInfo == null) return null;

        d = evList[fieldInfo.GetValue(p_object)];
        if (d == null) return null;

        return d.GetInvocationList();
    }

    

    public static void PrintControlEventDelegateList(System.Windows.Forms.Button btn, string eventName = "MouseMove")
    {

        PropertyInfo pi = btn.GetType().GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
        EventHandlerList ehl = (EventHandlerList)pi.GetValue(btn, null);//EventClick

        FieldInfo fieldInfo = (typeof(System.Windows.Forms.Control)).GetField("Event" + eventName, BindingFlags.Static | BindingFlags.NonPublic);
        Delegate d = ehl[fieldInfo.GetValue(null)];

        if (d == null)
        {
            Console.WriteLine("Typed Event \"{0}\" not exist in target control!", eventName);
            return;
        }

        foreach (Delegate del in d.GetInvocationList())
            Console.WriteLine(del.Method.Name);
    }



    /// <summary>
    /// 对于指定类中自定义事件,移除其中的委托链的全部订阅方法,
    /// 或者移除委托链中的指定方法名的订阅。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="c"></param>
    /// <param name="event_name"></param>
    /// <param name="methodname"></param>
    public static void RemoveEvent<T>(T c, string event_name, string methodname = "")
    {
        Delegate[] invokeList = GetObjectEventList_V2(c, event_name);
        if (invokeList == null) return;

        foreach (Delegate del in invokeList)
        {
            if (methodname!="" && del.Method.Name != methodname)
                continue;
            typeof(T).GetEvent(event_name).RemoveEventHandler(c, del);
            //Console.WriteLine("Remove an event of " + event_name);
        }
    }

    public static Delegate[] GetObjectEventList_V2(object p_object, string p_EventName)
    {
        FieldInfo _fieldInfo;
        Delegate _ObjDele;
        object _FieldValue;

        _fieldInfo = p_object.GetType().GetField(p_EventName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public);
        if (_fieldInfo == null) return null;
        _FieldValue = _fieldInfo.GetValue(p_object);

        if (_FieldValue == null || !(_FieldValue is Delegate)) return null;
        _ObjDele = (Delegate)_FieldValue;

        return _ObjDele.GetInvocationList();
    }



    #region Demo2


    public class TEST
    {
        public event EventHandler AA;

        public void Foo()
        {
            if (AA!=null)
            {
                AA(this,new EventArgs()); //invoke the event
            }
        }
    }

    public static void DemoUse2()
    {

        TEST obj_a = new TEST();
        obj_a.AA += obj_a_AA;
        obj_a.Foo();

        RemoveEvent<TEST>(obj_a, "AA");
        obj_a.Foo();

        Console.WriteLine("Finished!");

    }

    static void obj_a_AA(object sender, EventArgs e)
    {
        Console.WriteLine("Evnet rasied!");
    }
   
    #endregion


    #region Demo

    public static void DemoUse()
    {

        System.Windows.Forms.Button btn = new System.Windows.Forms.Button();
        btn.Click += new EventHandler(btn_Click);
        btn.Click += new EventHandler(btn_Click2);
        btn.Click += new EventHandler(btn_Click3);
        btn.MouseMove += btn_MouseMove;
        btn.MouseMove += btn_MouseMove2;


        // print before
        Console.WriteLine("Before");
        PrintControlEventDelegateList(btn);
        PrintControlEventDelegateList(btn, "Click");

        // del delegate
        DemoRemoveControlEvents(btn, "Click");

        // print after
        Console.WriteLine("After");
        PrintControlEventDelegateList(btn);
        PrintControlEventDelegateList(btn, "Click");



    }

    static void btn_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        throw new NotImplementedException();
    }

    static void btn_MouseMove2(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        throw new NotImplementedException();
    }

    static void btn_Click(object sender, EventArgs e)
    {
        Console.WriteLine("Click1");
    }

    static void btn_Click2(object sender, EventArgs e)
    {
        Console.WriteLine("Click2");
    }

    static void btn_Click3(object sender, EventArgs e)
    {
        Console.WriteLine("Click3");
    }

    #endregion


}

 

posted @ 2018-06-29 11:55  wenglabs  阅读(465)  评论(0编辑  收藏  举报