Получить имя процедуры из Sender

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Получить имя процедуры из Sender

Сообщение mirk » 12.03.2014 11:36:01

Вызываю ActionList1_Action1Execute(self);
Как мне в ActionList1_Action1Execute получить из Sender имя процедуры, где был вызван мой код?
Нашел только ClassName и UnitName, но это совсем не то :(
mirk
постоялец
 
Сообщения: 317
Зарегистрирован: 24.09.2007 10:03:39

Re: Получить имя процедуры из Sender

Сообщение wavebvg » 12.03.2014 12:11:36

Передать об этом информацию при/перед вызове процедуры.

В конкретном случае, нужно такой Sender, который может запомнить эту информацию, к примеру в поле tag для визуальных контролов. Если приложение однопоточное и работает только внутри формы/ДМ и/или видимость глобальная, можно перед вызовом процедуры выставлять нужные флаги (предварительно их стоит так же завести). А вообще, отследить стек вызовов можно, но тут даже RTTI не поможет, придётся анализировать динамическое состояние стека, что требует его статистический анализ.

ЗЫ Чаще всего возникновение такой проблемы говорит о какой-то архитектурной ошибке. Попробуйте "стейт машину" или подобное и не будет нужно делать таких вещей, как машину времени в коде. Ну или реализуйте это, многие будут Вам очень благодарны, а если это ещё и к отладчику приладите... :-)
wavebvg
постоялец
 
Сообщения: 355
Зарегистрирован: 28.02.2008 04:57:35

Re: Получить имя процедуры из Sender

Сообщение mirk » 12.03.2014 13:18:44

Передать об этом информацию при/перед вызове процедуры.

Так уже передаю self. Если он ничего не дает полезного, то зачем его передавать вообще?
mirk
постоялец
 
Сообщения: 317
Зарегистрирован: 24.09.2007 10:03:39

Re: Получить имя процедуры из Sender

Сообщение wavebvg » 12.03.2014 14:58:58

Self - это контекст объекта, иницировавшего вызов. Именно на основании этой информации строится дальнейшее выполнение программы, а знание названия метода приведёт лишь путанице. Выбирать действия нужно не по названию функции, а по информации из Self.

Если уж совсем приспичило, то можно вызвать примерно так:

Код: Выделить всё
...
ActionList1_Action1Execute(TObject(1));
...


И обработать в ActionList1_Action1Execute так:

Код: Выделить всё
...
case Integer(Self) of
1:...
end;
...


Но лучше завсти enum

Говоря об "архитектурной ошибке" я и имел ввиду, что "Полезное <> имя процедуры". Если у Вас есть полный контекст вызова (Self+Sender), зачем нужно знать статический элемент (имя метода/процедуры), вызвавшего метод?

Попробую объяснить (у меня это плохо получается, но попытка не пытка):
Предположим, Вам нужно знать метод, который вызвал тот или иной Action. Предположим у Вас есть имя, но что даст Вам знание этой функции? Перечислим варианты:
1. Вы сможете написать условный оператор и выполнить специфический код;
2. Вы сможете сохранить это название на будущее, к примеру, для отладки;
3. Вы передадите это название внешнему исполнителю, который перейдёт к выполнению аналогично 1 или 2.

Первый вариант охватывает все варианты использования этой возможности, когда на что-то влияет, второй не будем рассматривать вообще (логировать явно можно перед вызовом обработчика Action), за третий нужно как минимум руки отрывать, если вы пишите прикладные приложения.

Если Вам нужно добавить новый вызов из другой функции - это приводит к тому, что обработчик события нужно править (fail, выкидываем и пишем заного без использования имени процедуры в коде), но, возможно, есть какие-то действия только для вызова из избранных методов, а для всех остальных код выполняется обычным способом. Тогда у Вас есть возможность вызвать этот код до ОБРАБОТКИ Action в том самом методе, который и запустил Action, а можно создать отдельное событие на этот случай, чтобы не гадать о результате выполнения.

Выводы:
1. Необходимость знания названия метода, вызвавшего метод говорит о том, что Вам нужен третий метод, который уже знает, кем он вызван (на самом деле знает, что делать в текущей ситуации) или передать как параметр при вызове;
2. Просто необходимо создать ещё один Action и зарефакторить выделив общий код обработки;
3. Знать и использовать информацию о методе, вызвашем метод в самом методе очень вредно для будующего этого самого метода.
wavebvg
постоялец
 
Сообщения: 355
Зарегистрирован: 28.02.2008 04:57:35

Re: Получить имя процедуры из Sender

Сообщение mirk » 12.03.2014 15:52:35

второй не будем рассматривать вообще (логировать явно можно перед вызовом обработчика Action)

У меня именно второй вариант.
Нет желания дублировать запись в лог перед каждым вызовом обработчика Action, ведь можно сделать это в одном месте.
mirk
постоялец
 
Сообщения: 317
Зарегистрирован: 24.09.2007 10:03:39

Re: Получить имя процедуры из Sender

Сообщение wavebvg » 12.03.2014 17:07:19

Готового решения не видел и поискав - не нашел на просторах.
Вопрос отладки... Ну это будет очень и очень сложно сделать, потому что придётся в динамической памяти найти текущий стек, раскрутить его до адреса вызвавшего метода (а как его отличить в стеке-то???), потом найти для этого метода имя (RTTI может и не помочь) по адресу.
Для логов проще обернуть вызов ещё одним методом (для не LCL биндинга), в которую передавать строку для отладки c параметром. Вызовы от LCL биндингов писать в лог по названию компоненты, вызвавшей Action.
Такую задачу не очень просто решить в лоб, потому что язык-то компилируемый, а машине на название... Ей номер (адрес) подавай...
wavebvg
постоялец
 
Сообщения: 355
Зарегистрирован: 28.02.2008 04:57:35


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 224

Рейтинг@Mail.ru