Механизм отражения
Механизм отражения позволяет получить информацию об экземплярах, не зная заранее их тип. Во встроенном языке в пространстве Стд::Отражение
реализован ряд типов, которые позволяют, например:
- получать свойства экземпляров, перебирать их, читать и устанавливать их значения;
- создавать экземпляры типов, имена которых вычисляются во время работы приложения.
Перебор свойств типа
пер Тип = Контрагенты.ПолучитьТип()
для Свойство из Тип.ПолучитьСвойства()
знч Имя = Свойство.Имя
знч Типы = Свойство.Типы
знч ЧтениеЗначения = &Свойство.Получить
знч ЗаписьЗначения = &Свойство.Установить
;
Сериализация
для каждого Объект из МассивОбъектов
пер Свойства = Объект.ПолучитьТип().ПолучитьСвойства()
для каждого Свойство из Свойства
ФайлПриемник.Записать(Свойство.Имя, Свойство.Получить(Объект))
;
;
Обобщенный тип
Чтобы получить доступ к параметрам обобщенного типа, используется свойство ПараметрыТипа типа ЧитаемыйМассив<ЧитаемоеМ ножество<Тип>>
, т. е. массив, каждый элемент которого содержит множество типов, соответствующих одному из параметров.
Так, например, для типа Соответствие
, параметром которого является составной тип, свойство ПараметрыТипа
примет следующее значение:
знч Соответствие = новый Соответствие<Строка, Число|Булево>
знч ПараметрыТипаСоответствия = Соответствие.ПолучитьТип().ПараметрыТипа
знч ТипыКлюча = ПараметрыТипаСоответствия[0] // множество с одним элементом: Тип<Строка>
знч ТипыЗначения = ПараметрыТипаСоответствия[1] // множество из двух элементов: Тип<Число> и Тип<Булево>
Если это объект простого типа, то при обращении к полю ОбъектТипа.ПараметрыТипа
вернется пустой массив.
Пример использования механизма отражения для обобщенного типа
Предположим, что на основе данных из соответствия требуется заполнить строго типизированную структуру.
Пусть дан объект типа Соответствие<Строка, Объект>
, который содержит данные по именованным ключам, где ключ — имя свойства, значение — значение свойства:
знч Соответствие: Соответствие<Строка, Объект> =
{
"Ид": 42345234,
"ТелоСообщения": {
"Дата": Дата{2020-08-05},
"Текст": "проверка",
"ВремяДействия": 3600
},
"Получатели": ["В ася", "Петя"]
}
На основе этого объекта требуется заполнить строго типизированные структуры:
структура ТелоСообщения
пер Дата: Дата
пер Текст: Строка
пер ВремяДействия: Число
;
структура Сообщение
пер Ид: Число
пер ТелоСообщения: ТелоСообщения
пер Получатели: Массив<Строка>
;
При заполнении структуры можем проверить с помощью свойства ПараметрыТипа
, что свойства-массивы совместимы по параметрам типа:
метод ЗаполнитьОбъект(ОбъектДляЗаполнения: Объект, Данные: ЧитаемоеСоответствие<Строка, Объект?>)
знч ТипОбъекта = ОбъектДляЗаполнения.ПолучитьТип()
для Свойство из ТипОбъекта.ПолучитьСвойства()
пер ЗначениеИзСоответствия = Данные[Свойство.Имя.Русский]
// Проверим, что массивы совместимы
если Свойство.ПолучитьТип().МожетБытьПрисвоенВ(Тип<Массив<Объект>>)
и ЗначениеИзСоответствия.ПолучитьТип().МожетБытьПрисвоенВ(Тип<Массив<Объект>>)
и Свойство.ПолучитьТип().ПараметрыТипа.СодержитВсе(ЗначениеИзСоответствия.ПолучитьТип().ПараметрыТипа)
Свойство.Установить(ОбъектДляЗаполнения, ЗначениеИзСоответствия)
иначе
// Обработка скалярных значений и вложенных объектов
// пропущена для краткости примера
;
;
;
Копирование структуры
структура ФизическоеЛицо
пер Пол: Пол
пер Имя: Строка
пер Фамилия: Строка
пер Отчество: Строка
пер ДатаРождения: Дата
пер СНИЛС: Строка
;
// С помощью конструктора структур, использующих именованные параметры
метод КопияФизЛица(Источник: ФизическоеЛицо): ФизическоеЛицо
знч ПоляКопирования = новый Соответствие<Строка, Объект>
для Свойство из Источник.ПолучитьТип().ПолучитьСвойства()
ПоляКопирования.В ставить(
Свойство.Имя.ВСтроку(), // оно двуязычное
Свойство.Получить(Источник))
;
возврат Тип<ФизическоеЛицо>.СоздатьЭкземпляр(ПоляКопирования);
;
// Почленное копирование
метод КопияФизЛица2(Источник: ФизическоеЛицо): ФизическоеЛицо
знч Копия = новый ФизическоеЛицо
для Свойство из Источник.ПолучитьТип().ПолучитьСвойства()
Свойство.Установить(Копия, Свойство.Получить(Источник))
;
;
Создание экземпляра типа (позиционные параметры)
Передача аргументов в конструктор выполняется в позиционной форме, в порядке объявления.
метод ЗагрузитьИзJson(ИмяТипа:Строка, ДанныеВJson:ЧитаемоеСоответствие<Строка, Объект?>)
знч ТипОбъекта = НайтиТип(ИмяТипа)
знч Объект = ТипОбъекта.СоздатьЭкземпляр([])
для СвойствоJson из ДанныеВJson
Объект[СвойствоJson.Ключ] = СвойствоJson.Значение
;
;
Создание экземпляра типа (именованные параметры)
Передача аргументов в конструктор выполняется в именованной форме. Метод может применяться, когда конструктор объекта подразумевает использование параметров только в именованной форме.
метод ЗагрузитьИзJson(ИмяТипа:Строка, ДанныеВJson:ЧитаемоеСоответствие<Строка, Объект?>)
знч ТипОбъекта = НайтиТип(ИмяТипа)
Если ТипОбъекта.МожетБытьПрисвоенВ(Тип<Справочник.Объект>)
знч СправочникОбъект = ТипОбъекта.СоздатьЭкземпляр(ДанныеВJson) как неизвестно
СправочникОбъект.Записать()
;
;
Получение менеджера сущности по ссылке
метод ПолучитьМенеджерПоКлючу(Ключ: Сущность.Ключ): Одиночка
возврат ОтражениеСущности.ПоТипу(Ключ.ПолучитьТип()).ТипОдиночка.ПолучитьЭкземпляр()
;