Переключение на Главную Страницу Страницы: 1 [2] 3 4 5 ОтправитьПечать
Очень популярная тема (более 25 ответов) Подписка на события vs Перехватчик в каждом классе (число прочтений - 24507 )
AndreyM
Full Member
***
Отсутствует



Сообщений: 166
Местоположение: Харьков
Зарегистрирован: 13. Февраля 2008
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #15 - 13. Августа 2008 :: 13:36
Печать  
artbear писал(а) 13. Августа 2008 :: 13:24:
Что-то как-то запутанно у тебя в подписке реализовано.
Опиши, как ты выполняешь подписку - классы и методы последовательно.

Это сначала кажеться запутанно, вообще всё просто (не очень) и понятно. Щас опишу
Сразу оговорюсь: делал в лоб - не получилось такого функционала, поэтому сделал в обход. Как уже говорил, не все классы подписываются на события, а остаются классы, которые сами реализовывают перехват. Так вот именно для них пришлось так извратиться. Если в лоб, то всё очень просто.
Пишу...
  

Правильно поставленный вопрос, уже содержит половину ответа.
Наверх
ICQ  
IP записан
 
AndreyM
Full Member
***
Отсутствует



Сообщений: 166
Местоположение: Харьков
Зарегистрирован: 13. Февраля 2008
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #16 - 13. Августа 2008 :: 14:21
Печать  
Посмотрел, понял, почему не понятно... я буду подчеркивать то, чего нет в примере.

ПерехватчикГМ: там всё просто, включается перехват ГМ на себя, описывается глоб.процедура ПодписатьсяНаСобытияФормы.

Подписка на события формы сохраняется в классе-перехватчике для данного контекста формы, в список ПодпискаБазовыйФорма::_СписокСобытий.
При подписке, с помощью глоб.процедуры, т.к. мы не знаем класс-подписчик данной формы, то для сопоставления создана таблица ПодпискаПрехватчикГМ::_ОткрытыеКонтексты.

При первой подписке любого класса на события формы (хоть это будет в ВводНового(), ПриОткрытии(), ПослеОткрытия(), или в конце модуля, т.е. код, который выполняется до ПриОткрытии()) на эту форму будет создан класс-перехватчик и сохранен в таблицу ПодпискаПрехватчикГМ::_ОткрытыеКонтексты с помощью метода ЗадатьПерехватчикФормы(Конт, Класс=""), но перехват включен не будет (в переменную Класс возвращается ссылка на класс-перехватчик для данной формы). В 30-й строке "// иначе создаем класс для данного контекста..." идет проверка, какой класс (наследник от ПодпискаБазовый) нужно создать для данной формы

Затем, в СобытиеГМ_ПослеОткрытия включаем перехват данной формы.
А класс ПодпискаБазовыйФорма или его наследники запускают на выполнение события во всех подписавшихся классах и в классах-перехватчиках (Одиночки или ПодпискаНаследник)

Не знаю что писать - задай конкретный вопрос.
  

Правильно поставленный вопрос, уже содержит половину ответа.
Наверх
ICQ  
IP записан
 
AndreyM
Full Member
***
Отсутствует



Сообщений: 166
Местоположение: Харьков
Зарегистрирован: 13. Февраля 2008
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #17 - 13. Августа 2008 :: 14:30
Печать  
Класс ПодпискаБазовыйФорма:
Функция _ВыполнитьСобытиеФормы(ИмяСобытия,П1=0,П2=0,П3=0,П4=0,П5=0,П6=0) Экспорт
выполняет методы всех подписавшихся классов, классов-перехватчиков и формы (в конце)
Процедура _ПодписатьсяНаСобытияФормы(Класс,Знач ИмяСобытия) Экспорт
сохраняет в _СписокСобытий методы переданного Класс'а, разделяя их по именам событий, т.е. может быть описано Событие_ПриНажатииПравойКнопки или ПриНажатииПравойКнопки, но все они попадут в элемент списка ПриНажатииПравойКнопки.
Процедура ВключитьПерехват() Экспорт
включает перехват данного контекста данным классом

Класс ПодпискаПрехватчикГМ фактически только пользуется этими методами в начале, пока класс не включится в перехват
  

Правильно поставленный вопрос, уже содержит половину ответа.
Наверх
ICQ  
IP записан
 
Arta
1c++ power user
Отсутствует



Сообщений: 2537
Местоположение: Нижний Новгород
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #18 - 13. Августа 2008 :: 20:43
Печать  
AndreyM писал(а) 13. Августа 2008 :: 12:40:
А в наследнике:
Код
Выбрать все
Функция Событие_ПриНажатииПравойКнопки(Сост, Гор, Верт, ФСО) Экспорт
	Рез = База().Событие_ПриНажатииПравойКнопки(Сост, Гор, Верт, ФСО);
	Возврат Рез;
КонецФункции 


1. Зачем тебе возврат Рез, если есть ФСО?
2. Лучше делать так:

Родитель:
Код
Выбрать все
Процедура ПриНажатииКнопкиКлавиатуры(Код, Альт, Шифт, Контрол, Символ, ФСО) Экспорт
	Перехватчик.ВыполнитьОригинальноеСобытиеГК(Конт, "ПриНажатииКнопкиКлавиатуры", Код, Альт, Шифт, Контрол, Символ, ФСО);
 


Наследник:
Код
Выбрать все
Процедура ПриНажатииКнопкиКлавиатуры(Код, А, Ш, К, Символ, ФСО) Экспорт
	Вирт().ПолучитьБазовыйКласс().ПриНажатииКнопкиКлавиатуры(Код, А, Ш, К, Символ, ФСО);
КонецПроцедуры
 



У тебя же может быть несколько наследников в иерархии

  
Наверх
 
IP записан
 
AndreyM
Full Member
***
Отсутствует



Сообщений: 166
Местоположение: Харьков
Зарегистрирован: 13. Февраля 2008
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #19 - 14. Августа 2008 :: 06:06
Печать  
Arta писал(а) 13. Августа 2008 :: 20:43:
AndreyM писал(а) 13. Августа 2008 :: 12:40:
А в наследнике:
Код
Выбрать все
Функция Событие_ПриНажатииПравойКнопки(Сост, Гор, Верт, ФСО) Экспорт
	Рез = База().Событие_ПриНажатииПравойКнопки(Сост, Гор, Верт, ФСО);
	Возврат Рез;
КонецФункции 


1. Зачем тебе возврат Рез, если есть ФСО?

Рез - это флаг обрыва цепочки выполнения события (как в МенеджерСобытий), как я уже писал: "быстрый выход из цепочки обработки события, т.е., например, если класс обрабатывает определенный реквизит формы, то после того, как он сделал свое дело, возвращает 0 и вся цепочка события завершает свою работу, а не идет по стеку через все перехватчики формы",
а ФСО - это стандартная отмена события

И между Рез=База()... и Возврат Рез есть еще код, который выполняет, скажем так, основной класс формы: "классы с подпиской даны не в полном объеме и не со всеми возможностями, а только как пример, для понимания процесса подписки".

ЗЫ Про наследников (второй вопрос) напишу чуть позже
  

Правильно поставленный вопрос, уже содержит половину ответа.
Наверх
ICQ  
IP записан
 
AndreyM
Full Member
***
Отсутствует



Сообщений: 166
Местоположение: Харьков
Зарегистрирован: 13. Февраля 2008
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #20 - 14. Августа 2008 :: 06:11
Печать  
artbear писал(а) 13. Августа 2008 :: 13:24:
Что-то как-то запутанно у тебя в подписке реализовано.

Да, есть чуток - делалось без плана, а по мере нахождения обходных путей.
Щас малехо перелапачу подписку в сторону упрощения и уменьшения использования памяти.

Arta,
ты посеял у меня зерно сомнения с "несколькими наследниками" - буду пересматривать Улыбка
Беру тайм-аут   Подмигивание
  

Правильно поставленный вопрос, уже содержит половину ответа.
Наверх
ICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #21 - 14. Августа 2008 :: 06:20
Печать  
AndreyM писал(а) 14. Августа 2008 :: 06:06:
Arta писал(а) 13. Августа 2008 :: 20:43:
AndreyM писал(а) 13. Августа 2008 :: 12:40:
А в наследнике:
Код
Выбрать все
Функция Событие_ПриНажатииПравойКнопки(Сост, Гор, Верт, ФСО) Экспорт
	Рез = База().Событие_ПриНажатииПравойКнопки(Сост, Гор, Верт, ФСО);
	Возврат Рез;
КонецФункции 


1. Зачем тебе возврат Рез, если есть ФСО?

Рез - это флаг обрыва цепочки выполнения события (как в МенеджерСобытий), как я уже писал: "быстрый выход из цепочки обработки события, т.е., например, если класс обрабатывает определенный реквизит формы, то после того, как он сделал свое дело, возвращает 0 и вся цепочка события завершает свою работу, а не идет по стеку через все перехватчики формы",
а ФСО - это стандартная отмена события

Флаг обрыва цепочки выполнения ИМХО использовать не очень удобно, т.к. получается не универсально Печаль
Например, в цепочке куча универсальных обработчиков, которые не зависят друг от друга и обязательно должны выполнить некие действия.
Если первый из них тормознет всю цепочку, то остальные не выполнятся и будет косяк.
Поэтому, как правило, я не юзаю подобный флаг, а передаю спец. параметр события типа ФСО, которым и подсказываю, что кто-то где-то предлагает не выполнять стандартные действия.

Например, для событий Событие_ПриОткрытии ФСО = 0 в подписке означает, что форма не будет открыта, и обработчики могут в зависимости от этого выполнять или не выполнять свои действия.
Т.е. обработчик перехвата Событие_ПриОткрытии отправляет собственное событие Обработать_Событие_ПриОткрытии(Конт, ФСО, ...) всем подписчикам. Подписчики обязаны вернуть 1 в Обработать_Событие_ПриОткрытии, а вот ФСО могут менять.

Или еще надежнее, если форма может быть не открыта - ввести два собственных события:
Обработать_Проверку_Событие_ПриОткрытии - проверяем, будет ли форма открыта. Здесь цепочка может прерывать, и это правильно/быстро/удобно.
Обработать_Событие_ПриОткрытии - если форма будет точно открыта, то передаем событие подписчикам. Цепочка не может прерываться.
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer && tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
AndreyM
Full Member
***
Отсутствует



Сообщений: 166
Местоположение: Харьков
Зарегистрирован: 13. Февраля 2008
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #22 - 14. Августа 2008 :: 06:25
Печать  
Arta писал(а) 13. Августа 2008 :: 20:43:
2. Лучше делать так:

Родитель:
Код
Выбрать все
Процедура ПриНажатииКнопкиКлавиатуры(Код, Альт, Шифт, Контрол, Символ, ФСО) Экспорт
	Перехватчик.ВыполнитьОригинальноеСобытиеГК(Конт, "ПриНажатииКнопкиКлавиатуры", Код, Альт, Шифт, Контрол, Символ, ФСО);
 


Наследник:
Код
Выбрать все
Процедура ПриНажатииКнопкиКлавиатуры(Код, А, Ш, К, Символ, ФСО) Экспорт
	Вирт().ПолучитьБазовыйКласс().ПриНажатииКнопкиКлавиатуры(Код, А, Ш, К, Символ, ФСО);
КонецПроцедуры
 



У тебя же может быть несколько наследников в иерархии


Наверное еще не проснулся  Ужас
Уточни, это мы говорим о подписке или о БазовыйПерехватчик-НаследникПерехватчик?
  

Правильно поставленный вопрос, уже содержит половину ответа.
Наверх
ICQ  
IP записан
 
AndreyM
Full Member
***
Отсутствует



Сообщений: 166
Местоположение: Харьков
Зарегистрирован: 13. Февраля 2008
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #23 - 14. Августа 2008 :: 07:33
Печать  
artbear писал(а) 14. Августа 2008 :: 06:20:
Флаг обрыва цепочки выполнения ИМХО использовать не очень удобно, т.к. получается не универсально Печаль
Например, в цепочке куча универсальных обработчиков, которые не зависят друг от друга и обязательно должны выполнить некие действия.
Если первый из них тормознет всю цепочку, то остальные не выполнятся и будет косяк.
Поэтому, как правило, я не юзаю подобный флаг, а передаю спец. параметр события типа ФСО, которым и подсказываю, что кто-то где-то предлагает не выполнять стандартные действия.

Думал и об этом - у самого мнение раздвоилось. Сразу скажу: если бы использовал МенеджерСобытий - ситуация была бы таже. И у тебя в тестовой конфе в функции СобытиеГлобальногоМодуля(ВидСобытия, стрПараметры) такая же возможна ситуация, но дальше ты ее не обрабатываешь.
Из описания:
Синтаксис:
ПослатьСобытие(<Издатель>,<ДопПараметр>)
Назначение:
Метод посылает событие всем зарегистрировавшимся подписчикам на него.
...
Возвращаемое значение:
(Число)  1 - цепочка рассылки событий пройдена полностью, 0 - рассылка была прервана одним из подписчиков.

Для варианта подписки придумал правило, которое будет либо описано в инструкции по пользованию, либо код реализации подписки будет переделан (в принципе,  уже записал в план переделки).
Варианты:
1) классы, которые должны обязательно получить событие, описываются последними, т.е. выполняться будут первыми (по принципу Перехватчика);
2) в процедуре _ПодписатьсяНаСобытияФормы(Класс,Знач ИмяСобытия,ОбязательноПолучатьСобытие=0) при передаче флага ОбязательноПолучатьСобытие=1 будут получать событие даже в случае, если кто-то вернул 0 и могут восстановить или сбросить ФСО - т.е. установить/сбросить событие (т.е. нажмется клавиша или нет);
3) вариант для инструкции: (включает описание первого варианта) + "Все обработчики событий должны быть описаны как процедуры (т.е. возвращают 1 в любом случае и так описано в большинстве классов), либо, как функции, и возвращать 1. Если класс обрабатывает определенный реквизит или событие и он обработал "свой" реквизит или событие, то может вернуть 0, чтобы прервать цепочку событий и остальные классы не будут делать проверку, т.к. определили, что реквизит уже "не их". Либо класс, который обрабатывает какие-либо критические события (например, нельзя нажимать на эту кнопку), то возвращая 0, делает так, как если бы этого события небыло вовсе."

artbear писал(а) 14. Августа 2008 :: 06:20:
Например, для событий Событие_ПриОткрытии ФСО = 0 в подписке означает, что форма не будет открыта, и обработчики могут в зависимости от этого выполнять или не выполнять свои действия.

Так оно и работает: ФСО - это флаг выполнения события.
См.ниже

artbear писал(а) 14. Августа 2008 :: 06:20:
Подписчики обязаны вернуть 1 в Обработать_Событие_ПриОткрытии, а вот ФСО могут менять.

Зачем заводить Обработать_Событие_ПриОткрытии? Если точно так-же они "обязаны вернуть 1 ", т.е. делают Возврат 1, либо описываются как процедуры. Логика поведения не изменилась, но нет переменной. Согласен?

artbear писал(а) 14. Августа 2008 :: 06:20:
Или еще надежнее, если форма может быть не открыта - ввести два собственных события:
Обработать_Проверку_Событие_ПриОткрытии - проверяем, будет ли форма открыта.

Это и есть ФСО

artbear писал(а) 14. Августа 2008 :: 06:20:
... проверяем, будет ли форма открыта. Здесь цепочка может прерывать, и это правильно/быстро/удобно.

Это и есть Возврат 0

Т.е. ты описал те же действия/поведение, но другими словами. Согласен?  Улыбка
Или я не правильно понял?
  

Правильно поставленный вопрос, уже содержит половину ответа.
Наверх
ICQ  
IP записан
 
AndreyM
Full Member
***
Отсутствует



Сообщений: 166
Местоположение: Харьков
Зарегистрирован: 13. Февраля 2008
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #24 - 14. Августа 2008 :: 07:46
Печать  
AndreyM писал(а) 14. Августа 2008 :: 07:33:
artbear писал(а) 14. Августа 2008 :: 06:20:
Например, для событий Событие_ПриОткрытии ФСО = 0 в подписке означает, что форма не будет открыта, и обработчики могут в зависимости от этого выполнять или не выполнять свои действия.

Так оно и работает: ФСО - это флаг выполнения события.

Предвидя вопрос: "у события ПриОткрытии, и некоторых других, нет ФСО!" сразу скажу, что, т.к. управлением событий управляет класс ПодпискаБазовый, то есть. Я могу передавать в процедуру этот флаг и, соответственно, получать его, как и у ПриНажатии... и т.п. Или пользоваться СтатусВозврата()
  

Правильно поставленный вопрос, уже содержит половину ответа.
Наверх
ICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #25 - 14. Августа 2008 :: 08:10
Печать  
Нет, ты неверно меня понял.
Еще раз - есть цепочка полностью независимых подписчиков, которые ничего не знают друг о друге, и должны выполнить определенные события, если форма будет открыта.
Методика прерывания цепочки здесь абсолютно не подходит, т.к. должны сработать все подписчики.
В то же время любой подписчик может уметь указывать, что форма не будет открыта, и любой подписчик может учитывать это обстоятельство.

Поэтому и предлагается 2 события, а не одно.
В одном событии, например, невозможно для подписчика 1 узнать, будет ли форма открыта или нет. Только в двух -
в первом простая и шустрая проверка на открытие формы, можно с прерыванием цепочки
во втором уже основные действия с учетом флага открытия формы.

Только так.

ЗЫ так много систем построено, например, в той же Винде WM_CLOSE и WM_QUERY_CLOSE или WM_EndSession и WM_QUERY_ENDSESSION
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer &amp;&amp; tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #26 - 14. Августа 2008 :: 08:14
Печать  
Понимаешь, независимые обработчики - это наиболее универсально, поэтому и схема нужна специализированная.

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

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer &amp;&amp; tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #27 - 14. Августа 2008 :: 08:15
Печать  
И от порядка подписки ничего не должно зависеть, это опять же мешает универсальности Печаль
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer &amp;&amp; tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
AndreyM
Full Member
***
Отсутствует



Сообщений: 166
Местоположение: Харьков
Зарегистрирован: 13. Февраля 2008
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #28 - 14. Августа 2008 :: 08:25
Печать  
artbear писал(а) 14. Августа 2008 :: 08:10:
Поэтому и предлагается 2 события, а не одно.
В одном событии, например, невозможно для подписчика 1 узнать, будет ли форма открыта или нет. Только в двух -
в первом простая и шустрая проверка на открытие формы, можно с прерыванием цепочки
во втором уже основные действия с учетом флага открытия формы.

Только так.

ЗЫ так много систем построено, например, в той же Винде WM_CLOSE и WM_QUERY_CLOSE или WM_EndSession и WM_QUERY_ENDSESSION

Согласен, можно и так. Посылать некое событие Обработать_Проверку_Событие_ПриОткрытии с обрывом цепочки. Можно и ПриОткрытии использовать, как проверка возможности открытия, а ПослеОткрытия - как факт: открываем таки форму или нет.
Мы зацепились не за то: можно вообще убрать Возврат 0 и передавать события всем подписчикам (эту возможность описал, скажем так, "ради красного словца"). Всё-равно подписка сработает быстрее, чем базовый-наследник. Повторюсь, сделал я это по аналогии с Менеджером событий - считал, что если он так делает, то это необходимо

Интереснее, из ответа #23, какой вариант предпочтительней?
Хотелось бы узнать твое мнение и мнение форумчан. Или вообще ответ: не менять поведение, схожее с Перехватчиком.
Хотя, если в каком-либо классе не будет описано некое событие, которое используется в пред.перехватчике, то цепочка опять-таки порвется. Аналогично Возврат 0.
  

Правильно поставленный вопрос, уже содержит половину ответа.
Наверх
ICQ  
IP записан
 
AndreyM
Full Member
***
Отсутствует



Сообщений: 166
Местоположение: Харьков
Зарегистрирован: 13. Февраля 2008
Пол: Мужской
Re: Подписка на события vs Перехватчик в каждом кл
Ответ #29 - 14. Августа 2008 :: 08:26
Печать  
artbear писал(а) 14. Августа 2008 :: 08:15:
И от порядка подписки ничего не должно зависеть, это опять же мешает универсальности Печаль

Но так работает Перехватчик! Согласен?
  

Правильно поставленный вопрос, уже содержит половину ответа.
Наверх
ICQ  
IP записан
 
Переключение на Главную Страницу Страницы: 1 [2] 3 4 5
ОтправитьПечать