Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/18: Рейтинг темы: голосов - 18, средняя оценка - 5.00
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705

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

26.01.2013, 18:08. Показов 3675. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Не имя события- имя события и дурак получит. А само событие! Ну то есть: создадим форму и кинем на неё кнопку.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection; 
 
 
namespace WindowsFormsApplication6
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            
            //Вот так мы добавим обработчик события программно к кнопке
            this.button1.Click += new System.EventHandler(this.method);
 
            
            Type t = typeof(System.Windows.Forms.Button); 
            EventInfo [] e= t.GetEvents ();
 
            //Поехали программно перечислять события, связанные с этой кнопкой.
            for (int i = 0; i < e.Length; i++)
            {
                //А вот тут я пытаюсь программно добавить обработчик ко всем событиям    
                this.button1.(e[i]/*ЧЁ ТУТ ПИСАТЬ?*/)+=new System.EventHandler(this.method);
                   
                //Ну а вот так можно получить имя, это просто
                string ima= e[i].Name;
            }
        }
 
        private void method (object sender, EventArgs e)
        {
            //этот метод для понта просто
        }
    }
}
я так-то в объекте EventInfo нормально поковырялся. И в MemberInfo (базовый для EventInfo) тоже смотрел- ничё не нашёл.

C#
1
this.button1.Click
эта вот штука имеет тип EventHandler; вот поля такого типа и надо искать в недрах EventInfo, но у меня не получилось. Ребята, может вы мне поможете?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
26.01.2013, 18:08
Ответы с готовыми решениями:

Как получить доступ к приватному полю используя рефлексию? (в одном классе)
Хай. Есть такой класс class TestClass { public int a = 1; //находится private string b...

Как задать значения статического поля класса используя рефлексию?
Народ как задать значение статическому полю класса при помощи рефлексии. Есть тема...

Как получить элемент списка через рефлексию?
Добрый день, уважаемые гуру. List&lt;int&gt; v = new List&lt;int&gt;(); v.Add(10); v.Add(20); v.Add(30); Type t = v.GetType(); Как из...

15
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
26.01.2013, 18:31
C#
1
2
3
4
var events = typeof( Button ).GetEvents();
 
for ( int i = 0; i < events.Length; ++i )
    events[i].AddEventHandler( button1, new EventHandler( method ) );
Только ко всем событиям один и тот же обработчик не добавить, не все события основаны на делегате EventHandler.
1
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
26.01.2013, 18:36
Цитата Сообщение от SSTREGG Посмотреть сообщение
не все события основаны на делегате EventHandler
Ковариантность делегатов же, нет?
По крайней мере, для тех событий, у которых сигнатура делегата имеет object первым параметром и EventArgs вторым.
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
26.01.2013, 19:39
Угу, только у кнопки не все события основаны на EventHandler.

К примеру событие MouseDoubleClick основано на делегате MouseEventHandler, и при попытке подписаться на него используя EventHandler вылетит Exception о невозможности преобразования EventHandler к MouseEventHandler.

Добавлено через 12 минут
Можно так извернуться конечно
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        public Form1 ( )
        {
            InitializeComponent();
 
            var methodInfo = this.GetType().GetMethod( "method", BindingFlags.NonPublic | BindingFlags.Instance );
            var events = typeof( Button ).GetEvents();
 
            for ( int i = 0; i < events.Length; ++i )
                events[i].AddEventHandler( button1, Delegate.CreateDelegate( events[i].EventHandlerType, this, methodInfo ) );
        }
 
        void method ( object sender, EventArgs e )
        {
            Debug.WriteLine( sender );
        }
но зачем...
1
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
27.01.2013, 00:51  [ТС]
Ну я просто хочу узнать какие события создаются при том или ином действии. Не вручную же мне прописывать к каждому событию обработчик!

Добавлено через 4 часа 59 минут
SSTREGG, скажите пожалуйста, вот я взял ваш код и вот так переписал:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        public Form1()
        {
            InitializeComponent();
 
            //var methodInfo = this.GetType().GetMethod("method", BindingFlags.NonPublic | BindingFlags.Instance);
            var events = typeof(Button).GetEvents();
 
            for (int i = 0; i < events.Length; ++i)
            {
                events[i].AddEventHandler(button1, Delegate.CreateDelegate(events[i].EventHandlerType, this, "method"));
                
                int ind= dataGridView1.Rows.Add();
                dataGridView1.Rows[ind].Cells[0].Value = events[i].EventHandlerType.FullName;
            
            }    
        }
я, конечно мало надеялся, что он заработает, но тем не менее. Значит, смотрите ,он компилится, но при отладке выдаёт ошибку:
"Дополнительные сведения: Ошибка при связывании с конечным методом."
, что неудивительно, ведь для события, к примеру MouseEventHandler, нужен обработчик с совсем другими аргументами, нежели у меня. И вы сами об этом выше сказали.

А теперь ваш код. Вот строчка, которая у нас различается.
C#
1
 events[i].AddEventHandler(button1, Delegate.CreateDelegate(events[i].EventHandlerType, this, methodInfo));
, но глядя на синтаксис, и не видя результата, можно ведь и засомневаться- а почему, собсно, этот код должен работать, если мой не работает? Ведь смотрите последним параметром вы передаёте сведения о том же методе, что и я. Фактически мы передаём ОДНУ И ТУ ЖЕ ИНФУ- только я в имени метода (а больше нету метода "method", он уникален в этом адресном пространстве, хоть ты тресни), а вы в переменной methodInfo. Но оттого, что мы будем использовать ваш способ передачи информации о методе, он не станет ни таким:
C#
1
2
3
        private void method(object sender, System.ComponentModel.CancelEventArgs e)
        {
        }
ни таким
C#
1
2
3
        private void method(object sender, System.Windows.Forms.UICuesEventArgs e)
        {
        }
, ни ещё каким либо, таких прототипов я насчитал 16 штук

Ну вот вопрос- чем же таким различаются способы передачи мой и ваш, что ваш работает, а мой нет, если и в том и другом случае метод можно идентифицировать однозначно (он единственен)?

Может в MethodInfo флаг какой присутствует, навроде "закрыть глаза на типы аргументов"? Посмотрел, ничё не нашёл подобного... Уж я не знаю что и думать. Был бы благодарен, если бы объяснили.
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
27.01.2013, 01:36
Цитата Сообщение от kravam Посмотреть сообщение
Ну вот вопрос- чем же таким различаются способы передачи мой и ваш, что ваш работает, а мой нет, если и в том и другом случае метод можно идентифицировать однозначно
Внутренней реализацией.
Главным отличием является то какие флаги перечисления DelegateBindingFlags (внутренний тип) используются внутри этих методов, из-за этого и разный результат.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
    // These flags effect the way BindToMethodInfo and BindToMethodName are allowed to bind a delegate to a target method. Their
    // values must be kept in sync with the definition in vm\comdelegate.h.
    internal enum DelegateBindingFlags
    {
        StaticMethodOnly    =   0x00000001, // Can only bind to static target methods
        InstanceMethodOnly  =   0x00000002, // Can only bind to instance (including virtual) methods
        OpenDelegateOnly    =   0x00000004, // Only allow the creation of delegates open over the 1st argument
        ClosedDelegateOnly  =   0x00000008, // Only allow the creation of delegates closed over the 1st argument
        NeverCloseOverNull  =   0x00000010, // A null target will never been considered as a possible null 1st argument
        CaselessMatching    =   0x00000020, // Use case insensitive lookup for methods matched by name
        SkipSecurityChecks  =   0x00000040, // Skip security checks (visibility, link demand etc.)
        RelaxedSignature    =   0x00000080, // Allow relaxed signature matching (co/contra variance)
    }
Ваш способ:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        // V1 API.
        public static Delegate CreateDelegate(Type type, Object target, String method)
        {
            return CreateDelegate(type, target, method, false, true);
        }
 
            // .:: INTERNAL CALL ::.
            ...
            SomeFunc(..., DelegateBindingFlags.InstanceMethodOnly |
                                    DelegateBindingFlags.ClosedDelegateOnly |
                                    DelegateBindingFlags.NeverCloseOverNull |
                                    (ignoreCase ? DelegateBindingFlags.CaselessMatching : 0)))
 
            ...
Мой:
C#
1
2
3
4
5
6
7
8
9
public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method)
{
    return CreateDelegate(type, firstArgument, method, true);
}
 
// .:: INTERNAL CALL ::.
...
SomeFunc(..., DelegateBindingFlags.RelaxedSignature)
...
В моем случае видно что допускается использование ко/контр вариантности.
1
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
27.01.2013, 14:13  [ТС]
ладно, и теперь второй вопрос, как получить имя события в самом обработчике?
C#
1
2
3
4
private void method (object sender, EventArgs e)
        {
            //вот тут надо получить имя события  
        }
в общем на первый взгляд: из аргумента e особо ловить нечего, там всего два поля, каких-то малообнадёживающих. Да и по sender можно то же самое сказать.
...А получить-то надо!
0
Кодогенератор
 Аватар для hepper
200 / 200 / 51
Регистрация: 15.06.2011
Сообщений: 794
27.01.2013, 14:52
типа надо получить method ?
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
27.01.2013, 15:24  [ТС]
нет, метод я получу вот так:
C#
1
MethodBase.GetCurrentMethod().ToString();
Метод в данном случае это обработчик события. Вот надо в этом методе получить само событие ну или имя события на худой конец. Лучше само событие, имя-то я всяко-разно вытяну из него.
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
27.01.2013, 17:51
Кроме анализа стека вызовов больше ничего на ум не приходит
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        void method ( object sender, EventArgs e )
        {
            var frames = new StackTrace().GetFrames();
            var currentMethod = MethodBase.GetCurrentMethod();
            MethodBase raisedEvent = null;
 
            for ( int i = 0; i < frames.Length; ++i )
                if ( currentMethod == frames[i].GetMethod() )
                {
                    raisedEvent = frames[i + 1].GetMethod();
                    break;
                }
 
            if ( raisedEvent != null )
                Trace.WriteLine( raisedEvent.Name );
        }
1
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
27.01.2013, 18:04  [ТС]
Проникнитесь моим гениальным планом и пусть он вас взбодрит. То есть смысл такой: получить все события, которые возникают при том или ином действии. Чтобы не бежать каждый раз и не спрашивать, "а как установить курсор в ячейке dataGridView туда-то", а просто вешаем на все события dataGridView обработчики и работаем и смотрим: "Ага, вызываются такие-то события. Ага, вот после обработки такого события, курсор поместился ту-да-то. Ага, а в какой момент времени получена новая позиция курсора?" Анализ во общем.

Обработчики-то мы повесили автоматом. А вот как в каждом получить имя события, вызвавшего его- вот вопрос. Не то, чтобы я был таким ленивым в плане изучения нового, просто
Цитата Сообщение от SSTREGG Посмотреть сообщение
больше ничего на ум не приходит
звучит как: "то ли переполнится стек, то ли нет..."
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
27.01.2013, 18:08
Придумайте что-то лучше Направление есть.
Цитата Сообщение от kravam Посмотреть сообщение
Чтобы не бежать каждый раз и не спрашивать
А не надо "бежать каждый раз и спрашивать", всё это описано в MSDN.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
27.01.2013, 18:26
Цитата Сообщение от kravam Посмотреть сообщение
То есть смысл такой: получить все события, которые возникают при том или ином действии. Чтобы не бежать каждый раз и не спрашивать, "а как установить курсор в ячейке dataGridView туда-то", а просто вешаем на все события dataGridView обработчики и работаем и смотрим: "Ага, вызываются такие-то события. Ага, вот после обработки такого события, курсор поместился ту-да-то. Ага, а в какой момент времени получена новая позиция курсора?" Анализ во общем.
У вас же вроде как версия студии Ultimate?
В ее состав входит замечательная вещь под названием IntelliTrace - включается в настройках и позволяет делать именно то, что вам нужно без плясок с рефлексией.

Порой очень ее не хватает в моей Premium
1
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
27.01.2013, 20:55  [ТС]
К лирике мы ещё вернёмся. Щас поговорим о стеке. SSTREGG, я упростил ваш код. Ну то есть: кидаем кнопку на форму, кидаем туда же DataGridView лепим обработчик события Click и смотим, чё у нас лежит в стеке по вызову button1_Click
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        private void button1_Click(object sender, EventArgs e)
        {
            StackFrame [] frames = new StackTrace().GetFrames();
            for (int i = 0; i < frames.Length; ++i)
            {
                //Тут мы черпаем данные о функциях, которые запихнуты
                //в стек
                MethodBase ra = frames[i].GetMethod();
 
                //добавим новую строку к dataGridView1
                int ind = dataGridView1.Rows.Add();
                
                //И запихаем в неё имя метода, который лежит в стеке
                dataGridView1.Rows[ind].Cells[0].Value = ra.Name;
            
            }
        }
Ну и смотрим, чё получилось. Тщетно мы будем пытаться найти там имя события Click; там имена методов, да и чё там может ещё быть?
button1_Click
OnClick
OnClick
OnMouseUp
WmMouseUp
WndProc
WndProc
WndProc
OnMessage
WndProc
Callback
DispatchMessageW
System.Windows.Forms.UnsafeNativeMethods .IMsoComponentManager.FPushMessageLoop
RunMessageLoopInner
RunMessageLoop
Run
Main
в общем, не проканал такой способ.
Вопрос открыт.

Может быть, существует способ программно передать имя события или само событие параметром обработчику? Практика известная. (Создаём процесс- передаём указатель на собственные данные, создаём поток- то же самое; я щас не про C#)

Тогда можно было бы попытаться, коль скоро мы добавляем обработчики программно, при добавлении предусмотреть передачу парметром события? Так нет же:
C#
1
AddEventHandler(object, System.Delegate)
Ни хрена тут никуда особо не передашь... Обложили со всех сторон. Короче вопрос открыт, а я пошёл тра ковыряться с IntelliTrace
0
Почетный модератор
Эксперт .NET
 Аватар для NickoTin
8725 / 3677 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
27.01.2013, 21:29
Цитата Сообщение от kravam Посмотреть сообщение
OnClick
Ничего что все события в стандартных компонентах обернуты в методы OnИмяСобытия ?
И логично подумать что сразу за текущим методом в стеке будет храниться описание метода который возбудил определенное событие. И при условии что у события один подписчик, мы получим метод OnИмяСобытия, что в принципе и продемонстрировано Вашим выводом в DataGridView.
1
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
27.01.2013, 22:03  [ТС]
Цитата Сообщение от SSTREGG Посмотреть сообщение
И при условии что у события один подписчик
а если не один?
А впрочем, сие неважно. Навскидку- фрейм этого подписчика будет отсутствовать- ведь он либо закончил работу, либо и не начинал ещё. Значит, в стеке нет ни его имени, ни параметров. Правда, если два подписчика, стек выгляди так:

button1_Click
invoke
OnClick
ну, значит так надо. Авось разберусь. Условно говоря, вопрос решён.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
27.01.2013, 22:03
Помогаю со студенческими работами здесь

Как получить тело метода через рефлексию?
Скажите, а можно используя рефлексию вытащить тело метода в читабельном виде?

Получить список инстансов через рефлексию
Добрый вечер, подскажите пжл, как получить список всех инстансов (объектов) которые реализуют определенный класс или интерфейс? Получить...

Выполнение разных процедур одной и той же кнопкой
Option Explicit On Imports System Imports Microsoft.Win32 Imports System.IO Imports System.Text Imports System.ServiceProcess ...

Получить значение объекта своего типа через рефлексию
Доброго времени суток. Есть собственный тип с перегрузкой. public struct MyType { private string Prop{ get; set; } ...

Получить доступ к TryParse типа Enum через рефлексию
возникла необходимость восстановить значение перечисления System.Windows.Forms.FormWindowState из строки. Метода Parse или TryParse у этого...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru