Всем привет.

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

Подскажите, есть ли какой-то способ проверить наличие метода у объекта? Гугление по проблеме особо ничего не дало.
---
Готовая реализация в ИР - ирОбщий.МетодРеализованЛкс()
```1c
    Функция МетодРеализованЛкс(Объект, ИмяМетода) Экспорт
    Если Объект = Неопределено Тогда
    Возврат Ложь;
    КонецЕсли;
    Выражение = "Объект." + ИмяМетода + "(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)";
    Попытка
    Выполнить(Выражение);
    Исключение
    Инфо = ИнформацияОбОшибке();
    Описание = Инфо.Описание;
    КонецПопытки;
    Результат = Найти(НРег(Описание), "(" + НРег(ИмяМетода) + ")") = 0;
    Возврат Результат;
    КонецФункции
```
---
Автор пишет "Сейчас это работает в конструкции попытка-исключение, что мешает отладке.". Альтернативного, платформенного метода для этого нет.
---
Так его попытка наверняка считает отсутствием метода и посторонние ошибки от кода, исполняемого внутри вызванного метода. А моя - строго вызов конкретного метода проверяет.
---
вероятно следовало разделить справочники и документы на 2 разные подписки. Из доступных вариантов - проверять тип

```1c
    Если ТипЗнч(Источник) = Тип("СправочникОбъект.Сотрудники") Тогда
```
 или же документы, но это более точечно выбирать.
Можно проверить через
```1c
    Источник.Метаданные()
```
 например через имя ( Метаданные.Документы.Найти(Источник.Метаданные().Имя))
---
```1c
    Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Объект.Ссылка)) Тогда
    // Это справочник и его можно просто записать
    ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(Объект.Ссылка)) Тогда
    // Это документ, и его можно записывать с проведением
    ИначеЕсли...
    ....
    КонецЕсли;
```

Но есть засада - ТипВсеСсылки() не работает с объектами, добавленными в расширениях.
---
(5), Трудозатратно будет переписывать подписку, т.к. на ней много чего завязано. Прописывать условие для каждого объекта метаданных - тоже накладно. просто хотелось бы иметь возможность проверить, есть метод или нет, прежде чем вызывать.
---
Качество дешевым не бывает. Ну а раз нет времени на качественную разработку - то нет и смысла жаловать на отладку через попытку-исключение.
Хотя что тут страшного - в самом начале подписки определить вид объекта а одну переменную, а потом по тексту подставить в нужных местах условие (проверку этой переменной) перед вызовом спорных методов. Очень трудоёмко, согласен. Недели на две задачка.
---
как попытка мешает отладке?
---
При включенном режиме "Останавливаться по ошибке" - на всех эксепшнах останавливается, а если попытка еще и в цикле - мрак.
---
там опция есть : Останавливать только на ошибках включающих текст. Грамотное применение этой опции решит проблему на 99%

К тому же этих попыток в любой конфигурации как грязи - пусть тогда все попытки рефактурит в конфе, если они ему мешают.
---
трудозатраты большие. Настраивать отладчик каждый раз. Особенно при групповой разработке.
Я не спорю, попытка/исключение не есть зло само по себе, но раздаражет, когда она стоит в частоиспользуемом месте.
---
Попытка/исключение не есть зло само по себе - а вот разработчик сующий её во все части кода вместо проработки качественного кода - есть зло непосредственное и абсолютное.
У вас один конфигуратор на всю групповую разработку? Или что значит "трудно настраивать отладчик каждый раз при групповой разработке"?
---
а вот разработчик сующий её во все части кода вместо проработки качественного кода - есть зло непосредственное и абсолютное
именно поэтому сия ветка и создана, чтобы от такого кода избавиться. Спойлер: не избавиться.

(24) У вас один конфигуратор на всю групповую разработку? Или что значит "трудно настраивать отладчик каждый раз при групповой разработке"?
Это значит следующее: каждому разработчику придется заполнять и редактировать таблицу "Останавливать только на ошибках включающих текст", когда он захочет остановиться перед какой-то ошибкой. Плюс это ещё значит принципиальную невозможность отловить ошибки с текстом "Метод объекта не обнаружен". А если ещё представить, что такие ошибки могут вывалиться где-нибудь в транзакции, то вообще шик и блеск.
---
Групповая разработка - это хранилище конфигураций с захваченными объектами. И каждый в своём конфигурацией настраивает свои правила остановки по ошибке. В чем проблема-то?
---
в том, что каждому разработчику придётся настраивать свои правила остановки по ошибке
---
это проблема?
---
нашел вот такое

```1c
    Процедура ВыполнитьМетодОбъекта(Знач Объект, Знач ИмяМетода, Знач Параметры = Неопределено) Экспорт

    // Проверка имени метода на корректность.
    Попытка
    Тест = Новый Структура(ИмяМетода, ИмяМетода);
    Исключение
    ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
    НСтр("ru='Некорректное значение параметра ИмяМетода (%1) в ОбщегоНазначения.ВыполнитьМетодОбъекта';uk='Некоректне значення параметра ИмяМетода (%1) у ОбщегоНазначения.ВыполнитьМетодОбъекта'"), ИмяМетода);
    КонецПопытки;
```

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

```1c
    Выполнить "Объект." + ИмяМетода + "(" + ПараметрыСтрока + ")";
```
---
И что? Спорим, тоже в попытке?
---
нет. Вот полный код

```1c
    // Параметры:
    // Объект - Произвольный - объект встроенного языка, содержащий методы (например, ОбработкаОбъект).
    // ИмяМетода - Строка - имя экспортной процедуры модуля объекта обработки.
    // Параметры - Массив - параметры передаются в процедуру <ИмяПроцедуры>
    // в порядке расположения элементов массива.
    //
    Процедура ВыполнитьМетодОбъекта(Знач Объект, Знач ИмяМетода, Знач Параметры = Неопределено) Экспорт

    // Проверка имени метода на корректность.
    Попытка
    Тест = Новый Структура(ИмяМетода, ИмяМетода);
    Исключение
    ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
    НСтр("ru='Некорректное значение параметра ИмяМетода (%1) в ОбщегоНазначения.ВыполнитьМетодОбъекта';uk='Некоректне значення параметра ИмяМетода (%1) у ОбщегоНазначения.ВыполнитьМетодОбъекта'"), ИмяМетода);
    КонецПопытки;

    Если ПодсистемаСуществует("СтандартныеПодсистемы.ПрофилиБезопасности") Тогда
    МодульРаботаВБезопасномРежиме = ОбщийМодуль("РаботаВБезопасномРежиме");
    Если МодульРаботаВБезопасномРежиме.ИспользуютсяПрофилиБезопасности()
    И Не МодульРаботаВБезопасномРежиме.УстановленБезопасныйРежим() Тогда

    МодульРаботаВБезопасномРежиме = ОбщийМодуль("РаботаВБезопасномРежиме");
    ПрофильИнформационнойБазы = МодульРаботаВБезопасномРежиме.ПрофильБезопасностиИнформационнойБазы();

    Если ЗначениеЗаполнено(ПрофильИнформационнойБазы) Тогда

    УстановитьБезопасныйРежим(ПрофильИнформационнойБазы);
    Если БезопасныйРежим() = Истина Тогда
    УстановитьБезопасныйРежим(Ложь);
    КонецЕсли;

    КонецЕсли;

    КонецЕсли;
    КонецЕсли;

    ПараметрыСтрока = ";
    Если Параметры <> Неопределено И Параметры.Количество() > 0 Тогда
    Для Индекс = 0 По Параметры.ВГраница() Цикл
    ПараметрыСтрока = ПараметрыСтрока + "Параметры[" + Индекс + "],";
    КонецЦикла;
    ПараметрыСтрока = Сред(ПараметрыСтрока, 1, СтрДлина(ПараметрыСтрока) - 1);
    КонецЕсли;

    Выполнить "Объект." + ИмяМетода + "(" + ПараметрыСтрока + ")";

    КонецПроцедуры
```
---
ВыполнитьМетодОбъекта И он всегда вызывается в попытке...
Например

```1c
    Процедура Раз()
    Попытка
    Два();
    Исключение
    КонецПопытки;
    КонецПроцедуры

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

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

    КонецПроцедуры;
```
 И даже не спорьте - я наугад ткнул в пять мест этого методы в коде БСП
---
Готовая реализация в ИР - ирОбщий.МетодРеализованЛкс()
```1c
    Функция МетодРеализованЛкс(Объект, ИмяМетода) Экспорт
    Если Объект = Неопределено Тогда
    Возврат Ложь;
    КонецЕсли;
    Выражение = "Объект." + ИмяМетода + "(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)";
    Попытка
    Выполнить(Выражение);
    Исключение
    Инфо = ИнформацияОбОшибке();
    Описание = Инфо.Описание;
    КонецПопытки;
    Результат = Найти(НРег(Описание), "(" + НРег(ИмяМетода) + ")") = 0;
    Возврат Результат;
    КонецФункции
```
---
Автор пишет "Сейчас это работает в конструкции попытка-исключение, что мешает отладке.". Альтернативного, платформенного метода для этого нет.
---
Так его попытка наверняка считает отсутствием метода и посторонние ошибки от кода, исполняемого внутри вызванного метода. А моя - строго вызов конкретного метода проверяет.
---
Насколько я понимаю, вы проверяете наличие метода в модуле объекта. А автору, опять же насколько я понимаю, необходимы методы самого объекта, т.е. встроенные платформенные методы ДокументаОбъект, СправочникаОбъект и т.д. Это раз.
Второе. Проверять наличие метода его исполнением - ну так себе затея: фиг его знает, что он там себе исполняет в базе...
---
Оба твои предположения не верны. Моя проверка подходит для любого метода объекта, неважно встроенный он или прикладной. Я не исполняю метод, а вызываю его гарантировано некорректно. Поэтому он точно не будет выполнен.
---
а можно код ?
---
У тебя не отображается код в моем сообщении или тебе еще какой то код нужен?
---
Метод отличный, но не совсем то, что хотелось бы, к сожалению.
---
было бы хорошо чтобы встроили в платформу метод который бы возвращал список всех экспортных процедур...
---
Для этого придется встраивать методы в дерево конфигурации (и не только экспортный) и внутренний компилятор... Глобальная переработка платформы. Тянет на 10.0 )))
---
Метод уверен - лучший из возможных в текущей платформе. А наши желания к сожалению не помогут решать задачи в текущих условиях.
---
Может быть использовать фичу ком-объектов, когда методы ком-объекта могут быть получены как свойства?
---
Впервые слышу о таком, если честно. Но даже если так и есть, не представляю, как это можно использовать в данном случае
---
Придумал, как сделать, чтобы в попытке не мешало отладке. Но только на клиенте!

```1c
    // Есть экспортный метод
    //
    // Параметры:
    // Объект - Форма, ОбщийМодуль -
    // ИмяМетода - Строка -
    //
    // Возвращаемое значение:
    // - Булево
    //
    Функция ЕстьЭкспортныйМетод(Объект, ИмяМетода = "Подключаемый_ПродолжитьВыполнениеКомандыНаСервере") Экспорт

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

    Возврат Истина;

    КонецФункции
```
---
Сообщение было скрыто модератором.
---
Этот метод можно вставить в общий модуль (свойства модуля нужно установить как на картинке) и обращаться к нему из любого клиентского модуля.