|
v7: Как правильно выполнить обращение к переменной или функции по имени? ↓ (Волшебник 23.01.2024 08:53) |
☑ | ||
---|---|---|---|---|
0
Chai Nic
18.01.24
✎
11:33
|
Есть строковое значение, содержащее имя функции или переменной некого контекста. Как можно выполнить эту функцию и получить возвращаемое значение? Вроде как можно использовать Шаблон(), но у него два недостатка.
Первый - он может возвращать только строку. Второй - его невозможно красиво обернуть в попытку-исключение, если там внутри шаблона в квадратных скобках возникла ошибка - она выведется в окно сообщений в любом случае. Вот пример-иллюстрация в коде обработки. --- Перем Тест1; Функция ЗначениеПеременной(знач СтрокаЗначение) Попытка Возврат Шаблон("["+СтрокаЗначение+"]"); Исключение Возврат ""; КонецПопытки; КонецФункции Процедура Сформировать() Тест1=123; Сообщить(ЗначениеПеременной("Тест1")); Сообщить(ЗначениеПеременной("Тест2")); КонецПроцедуры --- Вот что выводится в окно сообщений. --- 123 Тест2<<?>> Переменная не определена (Тест2) [Тест2] --- Можно ли как-то сделать так, чтобы ошибка внутри шаблона перехватывалась? Или может есть какой-то другой способ для обращения к переменным и функциям контекста или выполнения произвольного кода? |
1 5 |
||
1
ADirks
18.01.24
✎
11:47
|
(0) используй FormEx или 1С++
|
2 |
||
2
Chai Nic
18.01.24
✎
11:51
|
(1) А поконкретнее? Какие там есть методы для программного обращения к коду, заданному строкой?
|
3 |
||
3
ADirks
18.01.24
✎
12:03
|
(2) например
- 1С++, оМодуль = СоздатьОбъект("ВыполняемыйМодуль"); Рез = 0; оМодуль.ВыполнитьФункциюКонтекста(Конт, ИмяМетода, сзАрг, Рез); Функция ПеременнаяКонтекста(Конт, ИмяПеременной) Экспорт ТекстМодуля = " |Функция ЗначениеПеременной() | Возврат "+ИмяПеременной+"; |КонецФункции |"; Модуль = СоздатьОбъект("ВыполняемыйМодуль"); Модуль.УстановитьМодуль(ТекстМодуля); Модуль.НазначитьКонтекст(Конт); Модуль.КомпилироватьМодуль(); Модуль.ВыполнитьМодуль(); Возврат Модуль.ЗначениеПеременной(); КонецФункции Функция УстановитьПеременную(Конт, ИмяПеременной, Значение) Экспорт ТекстМодуля = " |Функция УстЗнач(з) | "+ИмяПеременной+" = з; | Возврат "+ИмяПеременной+"; |КонецФункции |"; Модуль = Фаб.Модуль(Конт, ТекстМодуля); Возврат Модуль.УстЗнач(Значение); КонецФункции - FormEx оСервис = СоздатьОбъект("Сервис"); Рез = 0; оСервис.ВыполнитьФункцию(Конт, ИмяМетода, сзАрг, Рез); |
|||
4
SleepyHead
18.01.24
✎
14:15
|
||||
5
GrayS19
18.01.24
✎
14:23
|
(0) "Первый - он может возвращать только строку" - когда-то увидел как не только строку:
Значение = ЗначениеИзСтрокиВнутр(Шаблон("[ЗначениеВСтрокуВнутр("+ИмяРеквизитаФормы+")]")); // - это чтение реквизита формы через шаблон |
|||
6
Djelf
18.01.24
✎
15:32
|
Не надо так. Насколько помню, все 10 вариантов, кроме ВыполняемыйМодуль никто не умеет прочитать переменную ГМ.
Вопрос: зачем проверять в своем модуле переменную, с такими выкрутасами? Телепатирую: речь идет о ГММодуле, а это умеет только ВМ. Можно выкрутится и штатно, с переменной, через А=А; и проверкой дальше на ПустоеЗначение. Но возможно и в ГМ А=ПустоеЗначение(), так себе вариант, но так тоже можно. |
|||
7
victuan1
23.01.24
✎
06:32
|
Даже у себя я нашел такие "выкрутасы" ;)
Функция ИнитЕГАИС() Перем тщи; Попытка Модуль = СоздатьОбъект("ВыполняемыйМодуль"); //проверка того, что 1С++ была уже загружена Исключение Если ЗагрузитьВК("1cpp.dll",,Ссылка1СПП)=0 Тогда Возврат 0; КонецЕсли; КонецПопытки; Попытка МетаИнфо = СоздатьОбъект("MetaInfoClasses"); Версия = МетаИнфо.ПолучитьВерсиюФайла(); Исключение мсообщить("Неудачная попытка создания или использования объекта ""MetaInfoClasses"". Возможно, нужно установить более новую версию 1cpp.dll ("+Ссылка1СПП+")"); Возврат 0 КонецПопытки; Если Число(Версия) < 3 Тогда мсообщить("Установлена версия 1cpp.dll "+Версия+". Установите версию 1cpp.dll 3.х.х.х ("+Ссылка1СПП+")"); Возврат 0 КонецЕсли; //проверим объявлена ли глЕГАИС в осн. гл. модуле Попытка Если ПустоеЗначение(Модуль)=1 Тогда Модуль = СоздатьОбъект("ВыполняемыйМодуль"); КонецЕсли; Модуль.УстановитьМодуль("т = глЕГАИС"); Исключение мсообщить("Неудачная попытка использования объекта ""ВыполняемыйМодуль"". Возможно, нужно установить более новую версию 1cpp.dll ("+Ссылка1СПП+")"); Возврат 0 КонецПопытки; Попытка //Модуль.РазрешитьИсключения(); Модуль.КомпилироватьМодуль(); глЕГАИСобъявлена = 1; Исключение глЕГАИСобъявлена = 0; КонецПопытки; ИмяКласса = "ЕГАИС.Общие"; Если глЕГАИСобъявлена = 0 Тогда //задействуем Формекс для объявления глобальной переменной. Если глЕГАИС объявлена в осн. гл. модуле, то Формекс не используется и не загружается Попытка Серв = СоздатьОбъект("Сервис"); //проверка того, что Формекс была уже загружена Исключение Если ЗагрузитьВК("Formex.dll",,СсылкаФормекс)=0 Тогда Возврат 0; КонецЕсли; КонецПопытки; Попытка Если ПустоеЗначение(Серв)=1 Тогда Серв = СоздатьОбъект("Сервис"); КонецЕсли; Серв.ДобавитьГлобальныйМодуль("Перем глЕГАИС Экспорт;"); Исключение мсообщить("Неудачная попытка создания внешнего глобального модуля. Возможно, нужно установить более новую версию formex.dll ("+СсылкаФормекс+")"); Возврат 0 КонецПопытки; Иначе //проверим инициализирована ли переменная Шаблон("[глПрисвоить(тщи,глЕГАИС)]"); Если ТипЗначенияСтр(тщи)=ИмяКласса Тогда Возврат тщи КонецЕсли; КонецЕсли; Попытка Лицензия = СоздатьОбъект("КЗК2.Лицензия"); // проверка на загруженность компоненты Прекомпилятор, Исключение Если ЗагрузитьВК("precomp.dll") = 0 Тогда Возврат 0; //Иначе // Лицензия = СоздатьОбъект("КЗК2.Лицензия"); КонецЕсли; КонецПопытки; КлассЕсть = МетаИнфо.КлассСуществует(ИмяКласса); Если КлассЕсть =0 Тогда Если ИнитСпПутей()=0 Тогда Возврат 0 КонецЕсли; ФайлКласса = СтрЗаменить(ИмяКласса,".","_"); Если ФС.СуществуетФайл(КаталогОбработки+ФайлКласса+".ert")=0 Тогда мсообщить("Не найден файл реализации класса "+КаталогОбработки+ФайлКласса+".ert"+РазделительСтрок+"Возможно, нужно перезапустить обработку ""Обмен ЕГАИС"" для переопределения каталога хранения."); Возврат 0 КонецЕсли; Если ФС.СуществуетФайл(КаталогОбработки+ФайлКласса+".prm")=0 Тогда ТФайл= СоздатьОбъект("Текст"); ТФайл.ДобавитьСтроку("Класс "+ИмяКласса+"="+ФайлКласса+".ert{}"); Попытка ТФайл.Записать(КаталогОбработки+ФайлКласса+".prm"); ТФайл = ""; //обнуление ФС Исключение Сообщить("Ошибка при попытке записать файл "+КаталогОбработки+ФайлКласса+".prm: "+ОписаниеОшибки(), "!"); ТФайл = ""; //обнуление ФС возврат 0; КонецПопытки; КонецЕсли; Состояние("Инициализация класса "+ИмяКласса+" из файла "+КаталогОбработки+ФайлКласса+".ert"+"..."); Попытка МетаИнфо.ЗагрузитьОписаниеКлассов(КаталогОбработки+ФайлКласса+".prm"); Исключение мсообщить("Инициализация класса "+ИмяКласса+" закончилась неудачно!"); Возврат 0 КонецПопытки; Если МетаИнфо.КлассСуществует(ИмяКласса)=0 Тогда мсообщить("Не удалось загрузить класс "+ИмяКласса+" из файла "+КаталогОбработки+ФайлКласса+".ert"); Возврат 0; КонецЕсли; КонецЕсли; Попытка тщи = СоздатьОбъект(ИмяКласса); Исключение мсообщить(ОписаниеОшибки()); Возврат 0 КонецПопытки; тщи.КаталогОбработки = КаталогОбработки; тщи.СпПутей = СпПутей; Шаблон("[глПрисвоить(глЕГАИС,тщи)]"); тщи.Инит(); Возврат тщи КонецФункции |
|||
8
Волшебник
23.01.24
✎
08:53
|
хватит разврата
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |