Как получить все обработчики события из EventInfo?

96
12 мая 2021, 17:30

Как через рефлексию получить все обработчики события? Ведь, когда я добавляю обработчик, он должен сохраняться в какое-то приватное поле.

Answer 1

Класс для получения списка делегатов для обычных классов (не наследников от класса Component

using System;
using System.Linq;
using System.Reflection;
namespace WindowsFormsApp1
{
    public static class ReflectionHelper
    {
        public static Delegate[] GetSubscribedMethods(object instance, string eventName)
        {
            var type = instance.GetType();
            var currentEvent = type.GetEvents().FirstOrDefault(ev => ev.Name == eventName);
            if (currentEvent != null)
            {
                var eventFieldInfo = type.GetField(eventName,
                    BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);
                if (eventFieldInfo != null)
                {
                    var eventFieldValue = (Delegate)eventFieldInfo.GetValue(instance);
                    return eventFieldValue.GetInvocationList();
                }
            }
            return new Delegate[0];
        }
    }
}

И код с демонстрацией работы

using System;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
    public partial class MainForm : Form
    {
        private readonly Worker _worker;
        public MainForm()
        {
            InitializeComponent();
            Load += OnMainFormLoad;
            _worker = new Worker();
            _worker.SomeEvent1 += OnWorkerSomeEvent11;
            _worker.SomeEvent1 += OnWorkerSomeEvent12;
            _worker.SomeEvent2 += OnWorkerSomeEvent22;
        }
        private void OnWorkerSomeEvent11(object sender, EventArgs e)
        {
        }
        private void OnWorkerSomeEvent12(object sender, EventArgs e)
        {
        }
        private void OnWorkerSomeEvent22(object sender, EventArgs e)
        {
        }
        private void OnMainFormLoad(object sender, EventArgs e)
        {
            var clickEventHandlers = ReflectionHelper.GetSubscribedMethods(
                _worker, nameof(Worker.SomeEvent1));
            var lostFocusEventHandlers = ReflectionHelper.GetSubscribedMethods(
                _worker, nameof(Worker.SomeEvent2));
        }
    }
    public class Worker
    {
        public event EventHandler SomeEvent1;
        public event EventHandler SomeEvent2;
        public void DoWork()
        {
            SomeEvent1?.Invoke(this, EventArgs.Empty);
            SomeEvent2?.Invoke(this, EventArgs.Empty);
        }
    }
}

На примере Windows Forms приложения и кнопки

using System;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            Load += OnMainFormLoad;
            execButton.Click += OnButtonClick1;
            execButton.Click += OnButtonClick2;
            execButton.LostFocus += OButtonLostFocus;
        }
        private static Delegate[] GetInvocationListOfEvent(Control control, string eventName)
        {
            FieldInfo fieldInfo = typeof(Control).GetField(
                "Event" + eventName, BindingFlags.Static | BindingFlags.NonPublic);
            if (fieldInfo != null)
            {
                PropertyInfo pi = control.GetType().GetProperty("Events",
                    BindingFlags.NonPublic | BindingFlags.Instance);
                if (pi != null)
                {
                    var list = (EventHandlerList)pi.GetValue(control, null);
                    object obj = fieldInfo.GetValue(control);
                    return list[obj].GetInvocationList();
                }
            }
            return new Delegate[0];
        }
        private void OnMainFormLoad(object sender, EventArgs e)
        {
            var clickEventHandlers = GetInvocationListOfEvent(
                execButton, nameof(Control.Click));
            var lostFocusEventHandlers = GetInvocationListOfEvent(
                execButton, nameof(Control.LostFocus));
        }
        private void OButtonLostFocus(object sender, EventArgs e)
        {
        }
        private void OnButtonClick1(object sender, EventArgs e)
        {
        }
        private void OnButtonClick2(object sender, EventArgs e)
        {
        }
    }
}
READ ALSO
как вывести значения WaitForSeconds в unity c#

как вывести значения WaitForSeconds в unity c#

как показать отсчет времени при запуске/перезапуске сцены?

166
Миграция переводит названия таблиц в нижний регистр

Миграция переводит названия таблиц в нижний регистр

Проект ASPNET Core WebAPI, ORM EF Core, база данных MySQL, провайдер Pomelo

99
Не скрываются папки после обновления через функцию SHChangeNotify

Не скрываются папки после обновления через функцию SHChangeNotify

Сначала я отключаю просмотр всех скрытых файлов и папок через реестр: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced

130
Как бегущую строку сделать более плавной и гладкой?

Как бегущую строку сделать более плавной и гладкой?

Имеется код который запускает label и он движется ровно от середины до края

249