Как динамически установить значение свойства объекта по его имени в 1С 7.7

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С 7.7, особенно при использовании расширения 1С++ и технологии объектно-ориентированного программирования (КОП), часто возникает задача десериализации данных. Например, когда мы читаем XML-файл, мы получаем имя атрибута и его значение в виде строк. Стандартный подход с использованием условий Если...Тогда для каждого свойства быстро превращается в громоздкий и трудноподдерживаемый код («портянку»).

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

Способ 1: Использование штатной функции Шаблон

Самый простой, но имеющий свои ограничения способ — это использование функции Шаблон(). Этот метод позволяет исполнить фрагмент кода, переданный в виде строки. Однако в 1С 7.7 функция Шаблон предназначена для вычисления выражений, а не для прямого присваивания. Чтобы обойти это ограничение, мы создадим вспомогательную функцию-посредник.

Проанализируем пример реализации:


// Вспомогательная функция, которая выполняет присваивание
Функция УстАтрибут(пАтр, пЗн)
    пАтр = пЗн;
    Возврат ""; // Возвращаем пустую строку, чтобы Шаблон ничего не вывел
КонецФункции

// Основная процедура установки
Процедура УстановитьСвойствоКОП(пОбъект, пСвойство, пЗначение)
    // Формируем строку кода для выполнения
    Шаблон("[УстАтрибут(" + пОбъект + "." + пСвойство + ", пЗначение)]");
КонецПроцедуры

Важные нюансы:

Способ 2: Использование объекта ВыполняемыйМодуль (1С++)

Более мощный и профессиональный способ — использование объекта ВыполняемыйМодуль из состава 1С++. Он позволяет компилировать и выполнять произвольный код в контексте вашего объекта. Это работает быстрее и стабильнее, чем Шаблон.

Рассмотрим, как правильно организовать этот процесс внутри класса:


Перем ВМ; // Объект "ВыполняемыйМодуль"
Перем Свойство1 Экспорт;
Перем Свойство2 Экспорт;

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

Процедура УстановитьСвойство(ИмяПеременной, Значение) Экспорт
    // Формируем текст временной процедуры
    ТекстМодуля = "
    |Процедура ВыполнитьУстановку(Значение)
    |    " + ИмяПеременной + " = Значение;
    |КонецПроцедуры
    |";
    
    // Компилируем и запускаем
    ВМ.УстановитьМодуль(ТекстМодуля);
    ВМ.КомпилироватьИВыполнитьМодуль();
    ВМ.ВыполнитьУстановку(Значение);
КонецПроцедуры

Разберем по шагам, что здесь происходит. Мы создаем объект ВыполняемыйМодуль, который «знает» о контексте нашего класса (благодаря методу НазначитьКонтекст(Я())). При вызове установки мы динамически генерируем текст процедуры, где имя переменной подставляется прямо в код присваивания. Это позволяет работать с любыми типами данных без потери производительности на преобразование в строки.

Совет по оптимизации: Чтобы не перекомпилировать модуль при каждом вызове (что довольно затратно), можно один раз создать универсальную процедуру-диспетчер или использовать кэширование скомпилированных модулей.

Способ 3: Механизм динамических свойств 1С++

Если ваша задача — хранить произвольный набор данных из XML, рассмотрите использование динамических свойств. Вместо того чтобы описывать каждую переменную через Перем, вы можете перехватывать обращения к свойствам.

Проанализируем алгоритм работы через предопределенные методы класса:

  1. Внутри класса создайте объект Структура (или ИндексированнаяТаблица).
  2. Используйте метод ПриЗаписиДинамическогоСвойства(Имя, Значение).
  3. В этом методе просто сохраняйте данные в вашу внутреннюю структуру.

Это самый «красивый» способ с точки зрения архитектуры, так как он не требует динамической компиляции кода вообще. Объект будет «поглощать» любые атрибуты из XML, сохраняя их во внутренней коллекции.

Способ 4: Встроенная сериализация 1С++

Если вы сами управляете форматом сохранения, то 1С++ предлагает встроенные механизмы сериализации. Для этого в классе определяются специальные функции, которые позволяют платформе автоматически упаковывать и распаковывать состояние объекта.

Пример функций для поддержки сериализации:


Функция КлассСохраняемый()
    Возврат 1; // Указываем, что класс поддерживает сериализацию
КонецФункции

Функция СохранитьКлассВСтроку()
    // Здесь можно использовать ЗначениеВСтрокуВнутр для внутренней структуры
    Возврат ЗначениеВСтроку(ВажныеЗначения);
КонецФункции

Процедура ЗагрузитьИзСтроки(СтрДанных)
    // Восстанавливаем данные
    ВажныеЗначения = ЗначениеИзСтроки(СтрДанных);
КонецПроцедуры

Хотя автор вопроса упоминал необходимость работы именно с XML для внешних систем, данный метод полезен для внутреннего обмена данными между объектами 1С 7.7.

Проблема типов данных при десериализации

При получении данных из XML-атрибута мы всегда имеем дело со строкой. Выясним причину, почему простая установка значения может не сработать. Если свойство объекта в 1С должно быть числом или датой, простое присваивание строки может привести к ошибкам в дальнейших расчетах.

Для решения этой проблемы рекомендуется:

Резюме: Для разовых и простых задач подойдет метод с Шаблон(). Для массовой загрузки данных и сложных систем лучшим выбором будет ВыполняемыйМодуль или архитектура с динамическими свойствами через Структуру. Эти подходы позволяют сделать код десериализации XML лаконичным, состоящим всего из нескольких строк цикла по атрибутам узла.

← На главную