Перейти к основному содержимому

Механизм отражения

Механизм отражения позволяет получить информацию об экземплярах, не зная заранее их тип. Во встроенном языке в пространстве Стд::Отражение реализован ряд типов, которые позволяют, например:

  • получать свойства экземпляров, перебирать их, читать и устанавливать их значения;
  • создавать экземпляры типов, имена которых вычисляются во время работы приложения.

Перебор свойств типа

пер Тип = Контрагенты.ПолучитьТип()
для Свойство из Тип.ПолучитьСвойства()
знч Имя = Свойство.Имя
знч Типы = Свойство.Типы
знч ЧтениеЗначения = &Свойство.Получить
знч ЗаписьЗначения = &Свойство.Установить
;

Сериализация

для каждого Объект из МассивОбъектов
пер Свойства = Объект.ПолучитьТип().ПолучитьСвойства()
для каждого Свойство из Свойства
ФайлПриемник.Записать(Свойство.Имя, Свойство.Получить(Объект))
;
;

Обобщенный тип

Чтобы получить доступ к параметрам обобщенного типа, используется свойство ПараметрыТипа типа ЧитаемыйМассив<ЧитаемоеМножество<Тип>>, т. е. массив, каждый элемент которого содержит множество типов, соответствующих одному из параметров.

Так, например, для типа Соответствие, параметром которого является составной тип, свойство ПараметрыТипа примет следующее значение:

знч Соответствие = новый Соответствие<Строка, Число|Булево>
знч ПараметрыТипаСоответствия = Соответствие.ПолучитьТип().ПараметрыТипа

знч ТипыКлюча = ПараметрыТипаСоответствия[0] // множество с одним элементом: Тип<Строка>
знч ТипыЗначения = ПараметрыТипаСоответствия[1] // множество из двух элементов: Тип<Число> и Тип<Булево>

Если это объект простого типа, то при обращении к полю ОбъектТипа.ПараметрыТипа вернется пустой массив.

Пример использования механизма отражения для обобщенного типа

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

Пусть дан объект типа Соответствие<Строка, Объект>, который содержит данные по именованным ключам, где ключ — имя свойства, значение — значение свойства:

знч Соответствие: Соответствие<Строка, Объект> =
{
"Ид": 42345234,
"ТелоСообщения": {
"Дата": Дата{2020-08-05},
"Текст": "проверка",
"ВремяДействия": 3600
},
"Получатели": ["Вася", "Петя"]
}

На основе этого объекта требуется заполнить строго типизированные структуры:

структура ТелоСообщения
пер Дата: Дата
пер Текст: Строка
пер ВремяДействия: Число
;

структура Сообщение
пер Ид: Число
пер ТелоСообщения: ТелоСообщения
пер Получатели: Массив<Строка>
;

При заполнении структуры можем проверить с помощью свойства ПараметрыТипа, что свойства-массивы совместимы по параметрам типа:

метод ЗаполнитьОбъект(ОбъектДляЗаполнения: Объект, Данные: ЧитаемоеСоответствие<Строка, Объект?>)
знч ТипОбъекта = ОбъектДляЗаполнения.ПолучитьТип()
для Свойство из ТипОбъекта.ПолучитьСвойства()
пер ЗначениеИзСоответствия = Данные[Свойство.Имя.Русский]

// Проверим, что массивы совместимы
если Свойство.ПолучитьТип().МожетБытьПрисвоенВ(Тип<Массив<Объект>>)
и ЗначениеИзСоответствия.ПолучитьТип().МожетБытьПрисвоенВ(Тип<Массив<Объект>>)
и Свойство.ПолучитьТип().ПараметрыТипа.СодержитВсе(ЗначениеИзСоответствия.ПолучитьТип().ПараметрыТипа)

Свойство.Установить(ОбъектДляЗаполнения, ЗначениеИзСоответствия)

иначе
// Обработка скалярных значений и вложенных объектов
// пропущена для краткости примера
;
;
;

Копирование структуры

структура ФизическоеЛицо
пер Пол: Пол
пер Имя: Строка
пер Фамилия: Строка
пер Отчество: Строка
пер ДатаРождения: Дата
пер СНИЛС: Строка
;

// С помощью конструктора структур, использующих именованные параметры
метод КопияФизЛица(Источник: ФизическоеЛицо): ФизическоеЛицо
знч ПоляКопирования = новый Соответствие<Строка, Объект>
для Свойство из Источник.ПолучитьТип().ПолучитьСвойства()
ПоляКопирования.Вставить(
Свойство.Имя.ВСтроку(), // оно двуязычное
Свойство.Получить(Источник))
;

возврат Тип<ФизическоеЛицо>.СоздатьЭкземпляр(ПоляКопирования);
;

// Почленное копирование
метод КопияФизЛица2(Источник: ФизическоеЛицо): ФизическоеЛицо
знч Копия = новый ФизическоеЛицо
для Свойство из Источник.ПолучитьТип().ПолучитьСвойства()
Свойство.Установить(Копия, Свойство.Получить(Источник))
;
;

Создание экземпляра типа (позиционные параметры)

Передача аргументов в конструктор выполняется в позиционной форме, в порядке объявления.

метод ЗагрузитьИзJson(ИмяТипа:Строка, ДанныеВJson:ЧитаемоеСоответствие<Строка, Объект?>)

знч ТипОбъекта = НайтиТип(ИмяТипа)
знч Объект = ТипОбъекта.СоздатьЭкземпляр([])
для СвойствоJson из ДанныеВJson
Объект[СвойствоJson.Ключ] = СвойствоJson.Значение
;
;

Создание экземпляра типа (именованные параметры)

Передача аргументов в конструктор выполняется в именованной форме. Метод может применяться, когда конструктор объекта подразумевает использование параметров только в именованной форме.

метод ЗагрузитьИзJson(ИмяТипа:Строка, ДанныеВJson:ЧитаемоеСоответствие<Строка, Объект?>)

знч ТипОбъекта = НайтиТип(ИмяТипа)
Если ТипОбъекта.МожетБытьПрисвоенВ(Тип<Справочник.Объект>)
знч СправочникОбъект = ТипОбъекта.СоздатьЭкземпляр(ДанныеВJson) как неизвестно
СправочникОбъект.Записать()
;
;

Получение менеджера сущности по ссылке

метод ПолучитьМенеджерПоКлючу(Ключ: Сущность.Ключ): Одиночка
возврат ОтражениеСущности.ПоТипу(Ключ.ПолучитьТип()).ТипОдиночка.ПолучитьЭкземпляр()
;