Open tormozit opened 1 year ago
А как предлагается использовать <КонтекстныйОбъект>?
А как предлагается использовать <КонтекстныйОбъект>?
Если метод принадлежит модулю объекта (например СправочникОбъект или Форма), то вызывать его можно только от объекта, которому он принадлежит. Если конструктор вызывается внутри модуля, в котором есть метод-параметр, то можно не указывать объект - платформа сама его привяжет.
А если мы создали ссылку на метод от объекта, а потом объект вышел из области видимости (удален уже из памяти), а мы вызываем метод по ссылке? Должно вывалиться красивое исключение?
В-общем, примеров использования этого параметра не хватает.
А если мы создали ссылку на метод от объекта, а потом объект вышел из области видимости (удален уже из памяти)
Удаление объекта из памяти в такой ситуации невозможно. Ссылка на объект в ссылке метода будет удерживать объект в памяти.
Удаление объекта из памяти в такой ситуации невозможно. Ссылка на объект в ссылке метода будет удерживать объект в памяти.
Ладно. Не совсем из памяти.
Например,
&НаКлиенте
Процедура ОбработчикНажатияКнопки()
Ф1 = ПолучитьСсылкуНаФункциюНаСервере();
ВызовМетода Ф1(1, 2); // Здесь содержащего функцию объекта уже нет.
КонецПроцедуры
&НаСервере
Функция ПолучитьСсылкуНаФункциюНаСервере()
ТекущийОбъект = РеквизитФормыВЗначение("Объект");
Результат = Новый СсылкаМетода("РассчитатьСумму1", ТекущийОбъект);
Возврат Результат;
КонецФункции
Я по сути предлагаю опрятную замену существующим приемам через "Выполнить()". Исключения будут возникать аналогичные. Если объект не существует в текущем клиент-серверном контексте, то и вызвать его метод нельзя - будет исключение выброшено. Но скорее всего тип СсылкаМетода просто сделают несериализуемым и потому его нельзя будет передавать между клиентом и сервером.
Мне больше нравиться конструкция вызова, как то вот так:
СсылкаМетода.Выполнить(Параметры);
Или в идеале
СсылкаМетода = Новый СсылкаМетода(ИмяМетода, КонтекстныйОбъект);
СсылкаМетода(Параметры);
СсылкаМетода.Выполнить(Параметры);
Согласен. Так не придется расширять синтаксис языка. Переделал на твой вариант.
Думаю, что даже если на сервер добавят "ОписаниеОповещения", то этого бы хватило для большинства случаев. Объект можно передавать в качестве параметра. Да, описанное решение удобнее, но тут вопрос в сложности реализации на уровне платформы. Идеально всё же #14 , но если делать минимум, то можно просто ОписаниеОповещения на сервере позволять описывать.
ОписаниеОповещения слишком неудобно, т.к.
Отправлено боту 28.04.2023
Все же в некоторых случаях, например при подключении обработчика ожидания, будет удобно сразу в ссылке на метод указать значения параметров для вызова. Поэтому добавим опциональный 3-й параметр в конструктор аналогично объекту ОписаниеОповещения:
Новый СсылкаМетода(<ИмяМетода>, <КонтекстныйОбъект>[, <ЗначенияПараметров>])
Еще один костыльный способ вызывать по имени функцию с 3-мя параметрами (в 3-м передаваемая структура). Работает во всех контекстах при условии доступности экспорта методов.
Чт = Новый ЧтениеJSON;
Чт.УстановитьСтроку("{'r':1}");
я = ПрочитатьJSON(Чт,,,, "Функ", ЭтотОбъект, Струкутура);
Функция Функ(_1,_2, Струкутура) Экспорт
Сообщить(1);
КонецФункции
Уже есть заявка "Функции как объекты" https://github.com/SeiOkami/OneS/issues/14 Но она очень сложная в восприятии и, уверен, в реализации. Я же предлагаю намного более простой и потому реалистичный вариант - только ссылки на методы.
Иногда в реальных задачах приходится передавать метод1 как параметр в метод2. Таким образом метод2 не знает заранее какой конкретно метод он будет звать, но знает какие ему параметры передать. Например в БСП есть метод ОбновлениеИнформационнойБазы.ОбъектОбработан(), где в цикле вызывается ряд совпадающих по набору параметров динамически определяемых методов-проверок
Вычислить(СвойстваОбработчика.ПроцедураПроверки + "(МетаданныеИОтбор)")
У такого подхода есть неудобства:
Чтобы обойти эти проблемы и сделать подобный код более читаемым предлагаю добавить во встроенный язык простые исполняемые ссылки на методы.
Создаем ссылку метода через
Новый СсылкаМетода(<ИмяМетода>, <КонтекстныйОбъект>)
, где ИмяМетода - имя метода модуля или платформы, КонтекстныйОбъект - объект, которому принадлежит контекстный метод. Вызываем метод через ссылку двумя способамиЭто похоже на упрощенные делегаты (без обозначения параметров) других языков программирования. В качестве бонуса мы получаем
Пример
https://paste1c.ru/3z4hhwyxatoc По сравнению с Выполнить("<ИмяМетода>(...)") вызов через ссылку будет безопаснее и главное - намного быстрее за счет отсутствия динамической компиляции, что важно при частых вызовах, например для расчета каких то свойств в элементах коллекций.
Еще часто предлагают ОписаниеОповещения в качестве ссылки на метод. Объясняю почему оно не подходит
https://partners.v8.1c.ru/forum/topic/2128179