Как определить, существует ли метод объекта?

1. Drivingblind 228 24.09.20 15:45 Сейчас в теме
Всем привет.

Вопрос следующий: есть подписка на событие, которая вызывает метод объекта. Но этот метод у объекта может быть не всегда. Например, подписка на все справочники или документы.
Сейчас это работает в конструкции попытка-исключение, что мешает отладке.

Подскажите, есть ли какой-то способ проверить наличие метода у объекта? Гугление по проблеме особо ничего не дало.
По теме из базы знаний
Найденные решения
3. tormozit 7143 24.09.20 15:50 Сейчас в теме
Готовая реализация в ИР - ирОбщий.МетодРеализованЛкс()
Функция МетодРеализованЛкс(Объект, ИмяМетода) Экспорт
	Если Объект = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;
	Выражение = "Объект." + ИмяМетода + "(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)";
	Попытка
		Выполнить(Выражение);
	Исключение
		Инфо = ИнформацияОбОшибке();
		Описание = Инфо.Описание;
	КонецПопытки;
	Результат = Найти(НРег(Описание), "(" + НРег(ИмяМетода) + ")") = 0;
	Возврат Результат;
КонецФункции
Показать
ansverrr; EvgeTrofi; user1619761; Жолтокнижниг; Drivingblind; +5 Ответить
4. PerlAmutor 129 24.09.20 15:56 Сейчас в теме
(3) Автор пишет "Сейчас это работает в конструкции попытка-исключение, что мешает отладке.". Альтернативного, платформенного метода для этого нет.
Drivingblind; +1 Ответить
8. tormozit 7143 24.09.20 16:25 Сейчас в теме
(4) Так его попытка наверняка считает отсутствием метода и посторонние ошибки от кода, исполняемого внутри вызванного метода. А моя - строго вызов конкретного метода проверяет.
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. BackinSoda 24.09.20 15:48 Сейчас в теме
(1) вероятно следовало разделить справочники и документы на 2 разные подписки. Из доступных вариантов - проверять тип
Если ТипЗнч(Источник) = Тип("СправочникОбъект.Сотрудники") Тогда
или же документы, но это более точечно выбирать.
Можно проверить через
 Источник.Метаданные()
например через имя ( Метаданные.Документы.Найти(Источник.Метаданные().Имя))
5. FatPanzer 24.09.20 16:10 Сейчас в теме
(1)
Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Объект.Ссылка)) Тогда
    // Это справочник и его можно просто записать
ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(Объект.Ссылка)) Тогда
    // Это документ, и его можно записывать с проведением
ИначеЕсли...
    ....
КонецЕсли;

Но есть засада - ТипВсеСсылки() не работает с объектами, добавленными в расширениях.
20. Drivingblind 228 25.09.20 05:44 Сейчас в теме
(2)
(5), Трудозатратно будет переписывать подписку, т.к. на ней много чего завязано. Прописывать условие для каждого объекта метаданных - тоже накладно. просто хотелось бы иметь возможность проверить, есть метод или нет, прежде чем вызывать.
23. FatPanzer 25.09.20 08:39 Сейчас в теме
(20) Качество дешевым не бывает. Ну а раз нет времени на качественную разработку - то нет и смысла жаловать на отладку через попытку-исключение.
Хотя что тут страшного - в самом начале подписки определить вид объекта а одну переменную, а потом по тексту подставить в нужных местах условие (проверку этой переменной) перед вызовом спорных методов. Очень трудоёмко, согласен. Недели на две задачка.
6. Азбука Морзе 105 24.09.20 16:10 Сейчас в теме
(1) как попытка мешает отладке?
7. FatPanzer 24.09.20 16:11 Сейчас в теме
(6) При включенном режиме "Останавливаться по ошибке" - на всех эксепшнах останавливается, а если попытка еще и в цикле - мрак.
12. Азбука Морзе 105 24.09.20 16:38 Сейчас в теме
(7) там опция есть : Останавливать только на ошибках включающих текст. Грамотное применение этой опции решит проблему на 99%

К тому же этих попыток в любой конфигурации как грязи - пусть тогда все попытки рефактурит в конфе, если они ему мешают.
21. Drivingblind 228 25.09.20 05:49 Сейчас в теме
(12) трудозатраты большие. Настраивать отладчик каждый раз. Особенно при групповой разработке.
Я не спорю, попытка/исключение не есть зло само по себе, но раздаражет, когда она стоит в частоиспользуемом месте.
24. FatPanzer 25.09.20 08:42 Сейчас в теме
(21) Попытка/исключение не есть зло само по себе - а вот разработчик сующий её во все части кода вместо проработки качественного кода - есть зло непосредственное и абсолютное.
У вас один конфигуратор на всю групповую разработку? Или что значит "трудно настраивать отладчик каждый раз при групповой разработке"?
29. Drivingblind 228 04.10.20 16:35 Сейчас в теме
(24)
а вот разработчик сующий её во все части кода вместо проработки качественного кода - есть зло непосредственное и абсолютное

именно поэтому сия ветка и создана, чтобы от такого кода избавиться. Спойлер: не избавиться.

(24)
У вас один конфигуратор на всю групповую разработку? Или что значит "трудно настраивать отладчик каждый раз при групповой разработке"?

Это значит следующее: каждому разработчику придется заполнять и редактировать таблицу "Останавливать только на ошибках включающих текст", когда он захочет остановиться перед какой-то ошибкой. Плюс это ещё значит принципиальную невозможность отловить ошибки с текстом "Метод объекта не обнаружен". А если ещё представить, что такие ошибки могут вывалиться где-нибудь в транзакции, то вообще шик и блеск.
31. FatPanzer 04.10.20 17:27 Сейчас в теме
(29) Групповая разработка - это хранилище конфигураций с захваченными объектами. И каждый в своём конфигурацией настраивает свои правила остановки по ошибке. В чем проблема-то?
32. Drivingblind 228 04.10.20 17:37 Сейчас в теме
(31) в том, что каждому разработчику придётся настраивать свои правила остановки по ошибке
33. FatPanzer 04.10.20 18:05 Сейчас в теме
11. alex-l19041 8 24.09.20 16:36 Сейчас в теме
(1) нашел вот такое
 Процедура ВыполнитьМетодОбъекта(Знач Объект, Знач ИмяМетода, Знач Параметры = Неопределено) Экспорт
	
	// Проверка имени метода на корректность.
	Попытка
		Тест = Новый Структура(ИмяМетода, ИмяМетода);
	Исключение
		ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru='Некорректное значение параметра ИмяМетода (%1) в ОбщегоНазначения.ВыполнитьМетодОбъекта';uk='Некоректне значення параметра ИмяМетода (%1) у ОбщегоНазначения.ВыполнитьМетодОбъекта'"), ИмяМетода);
	КонецПопытки; 
Показать

но как работает проверка ? кто-то может объяснить?
13. FatPanzer 24.09.20 16:41 Сейчас в теме
(11) Это не проверка наличия метода. Это проверка корректности имени переменной, метода, ключа перед последующим использованием в выражениях.
user1619761; Drivingblind; +2 Ответить
14. alex-l19041 8 24.09.20 16:44 Сейчас в теме
(13) так там дальше
Выполнить "Объект." + ИмяМетода + "(" + ПараметрыСтрока + ")";
15. FatPanzer 24.09.20 16:47 Сейчас в теме
(14) И что? Спорим, тоже в попытке?
16. alex-l19041 8 24.09.20 16:49 Сейчас в теме
(15) нет. Вот полный код
// Параметры:
//  Объект    - Произвольный - объект встроенного языка, содержащий методы (например, ОбработкаОбъект).
//  ИмяМетода - Строка       - имя экспортной процедуры модуля объекта обработки.
//  Параметры - Массив       - параметры передаются в процедуру <ИмяПроцедуры>
//                             в порядке расположения элементов массива.
//
Процедура ВыполнитьМетодОбъекта(Знач Объект, Знач ИмяМетода, Знач Параметры = Неопределено) Экспорт
	
	// Проверка имени метода на корректность.
	Попытка
		Тест = Новый Структура(ИмяМетода, ИмяМетода);
	Исключение
		ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru='Некорректное значение параметра ИмяМетода (%1) в ОбщегоНазначения.ВыполнитьМетодОбъекта';uk='Некоректне значення параметра ИмяМетода (%1) у ОбщегоНазначения.ВыполнитьМетодОбъекта'"), ИмяМетода);
	КонецПопытки;
	
	Если ПодсистемаСуществует("СтандартныеПодсистемы.ПрофилиБезопасности") Тогда
		МодульРаботаВБезопасномРежиме = ОбщийМодуль("РаботаВБезопасномРежиме");
		Если МодульРаботаВБезопасномРежиме.ИспользуютсяПрофилиБезопасности()
			И Не МодульРаботаВБезопасномРежиме.УстановленБезопасныйРежим() Тогда
			
			МодульРаботаВБезопасномРежиме = ОбщийМодуль("РаботаВБезопасномРежиме");
			ПрофильИнформационнойБазы = МодульРаботаВБезопасномРежиме.ПрофильБезопасностиИнформационнойБазы();
			
			Если ЗначениеЗаполнено(ПрофильИнформационнойБазы) Тогда
				
				УстановитьБезопасныйРежим(ПрофильИнформационнойБазы);
				Если БезопасныйРежим() = Истина Тогда
					УстановитьБезопасныйРежим(Ложь);
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЕсли;
	КонецЕсли;
	
	ПараметрыСтрока = "";
	Если Параметры <> Неопределено И Параметры.Количество() > 0 Тогда
		Для Индекс = 0 По Параметры.ВГраница() Цикл 
			ПараметрыСтрока = ПараметрыСтрока + "Параметры[" + Индекс + "],";
		КонецЦикла;
		ПараметрыСтрока = Сред(ПараметрыСтрока, 1, СтрДлина(ПараметрыСтрока) - 1);
	КонецЕсли;
	
	Выполнить "Объект." + ИмяМетода + "(" + ПараметрыСтрока + ")";
	
КонецПроцедуры
Показать
18. FatPanzer 24.09.20 16:56 Сейчас в теме
(16)
ВыполнитьМетодОбъекта
И он всегда вызывается в попытке...
Например
Процедура Раз()
    Попытка
        Два();
    Исключение
    КонецПопытки;
КонецПроцедуры

Процедура Два()
    ВыполнитьМетодОбъекта();
КонецПроцедуры;

Процедура ВыполнитьМетодОбъекта()

КонецПроцедуры;
Показать
И даже не спорьте - я наугад ткнул в пять мест этого методы в коде БСП
Drivingblind; +1 Ответить
3. tormozit 7143 24.09.20 15:50 Сейчас в теме
Готовая реализация в ИР - ирОбщий.МетодРеализованЛкс()
Функция МетодРеализованЛкс(Объект, ИмяМетода) Экспорт
	Если Объект = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;
	Выражение = "Объект." + ИмяМетода + "(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)";
	Попытка
		Выполнить(Выражение);
	Исключение
		Инфо = ИнформацияОбОшибке();
		Описание = Инфо.Описание;
	КонецПопытки;
	Результат = Найти(НРег(Описание), "(" + НРег(ИмяМетода) + ")") = 0;
	Возврат Результат;
КонецФункции
Показать
ansverrr; EvgeTrofi; user1619761; Жолтокнижниг; Drivingblind; +5 Ответить
4. PerlAmutor 129 24.09.20 15:56 Сейчас в теме
(3) Автор пишет "Сейчас это работает в конструкции попытка-исключение, что мешает отладке.". Альтернативного, платформенного метода для этого нет.
Drivingblind; +1 Ответить
8. tormozit 7143 24.09.20 16:25 Сейчас в теме
(4) Так его попытка наверняка считает отсутствием метода и посторонние ошибки от кода, исполняемого внутри вызванного метода. А моя - строго вызов конкретного метода проверяет.
9. FatPanzer 24.09.20 16:29 Сейчас в теме
(8) Насколько я понимаю, вы проверяете наличие метода в модуле объекта. А автору, опять же насколько я понимаю, необходимы методы самого объекта, т.е. встроенные платформенные методы ДокументаОбъект, СправочникаОбъект и т.д. Это раз.
Второе. Проверять наличие метода его исполнением - ну так себе затея: фиг его знает, что он там себе исполняет в базе...
alex-l19041; Fox-trot; +2 1 Ответить
17. tormozit 7143 24.09.20 16:55 Сейчас в теме
(9) Оба твои предположения не верны. Моя проверка подходит для любого метода объекта, неважно встроенный он или прикладной. Я не исполняю метод, а вызываю его гарантировано некорректно. Поэтому он точно не будет выполнен.
Drivingblind; +1 Ответить
10. alex-l19041 8 24.09.20 16:32 Сейчас в теме
19. tormozit 7143 24.09.20 19:24 Сейчас в теме
(10) У тебя не отображается код в моем сообщении или тебе еще какой то код нужен?
22. Drivingblind 228 25.09.20 07:27 Сейчас в теме
(17) Метод отличный, но не совсем то, что хотелось бы, к сожалению.
25. alex-l19041 8 25.09.20 09:01 Сейчас в теме
(22) было бы хорошо чтобы встроили в платформу метод который бы возвращал список всех экспортных процедур...
26. FatPanzer 25.09.20 09:21 Сейчас в теме
(25) Для этого придется встраивать методы в дерево конфигурации (и не только экспортный) и внутренний компилятор... Глобальная переработка платформы. Тянет на 10.0 )))
27. tormozit 7143 25.09.20 09:27 Сейчас в теме
(22) Метод уверен - лучший из возможных в текущей платформе. А наши желания к сожалению не помогут решать задачи в текущих условиях.
Drivingblind; +1 Ответить
28. SlavaKron 25.09.20 09:38 Сейчас в теме
Может быть использовать фичу ком-объектов, когда методы ком-объекта могут быть получены как свойства?
30. Drivingblind 228 04.10.20 16:38 Сейчас в теме
(28) Впервые слышу о таком, если честно. Но даже если так и есть, не представляю, как это можно использовать в данном случае
34. EvgeTrofi 127 26.08.23 14:21 Сейчас в теме
Придумал, как сделать, чтобы в попытке не мешало отладке. Но только на клиенте!
// Есть экспортный метод
//
// Параметры:
//  Объект		 - Форма, ОбщийМодуль - 
//  ИмяМетода	 - Строка - 
// 
// Возвращаемое значение:
//   - Булево
//
Функция ЕстьЭкспортныйМетод(Объект, ИмяМетода = "Подключаемый_ПродолжитьВыполнениеКомандыНаСервере") Экспорт

	Попытка
		ОписаниеОповещения = Новый ОписаниеОповещения(ИмяМетода, Объект);
	Исключение
		Возврат Ложь;
	КонецПопытки;
	
	Возврат Истина;

КонецФункции
Показать
35. пользователь 26.08.23 16:19
Сообщение было скрыто модератором.
...
36. EvgeTrofi 127 26.08.23 16:37 Сейчас в теме
(35) Этот метод можно вставить в общий модуль (свойства модуля нужно установить как на картинке) и обращаться к нему из любого клиентского модуля.
Прикрепленные файлы:
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот