annotations
Библиотека для работы с аннотациями как с объектами первого класса. Позволяет описывать параметры аннотаций и их значения, а также получать их в виде объектов. Поддерживает механизм мета-аннотаций (аннотаций-агрегаторов других аннотаций).
Публичный интерфейс библиотеки описан в разделе api.
Зачем это нужно
В OneScript аннотации (&ИмяАннотации) можно навешивать на методы, свойства и параметры конструктора. С помощью reflector их можно прочитать в виде таблицы значений, но «сырые» аннотации — это просто набор строк и нетипизированных параметров. Разработчику приходится самостоятельно:
- проверять, что переданы все обязательные параметры;
- подставлять значения по умолчанию;
- следить за тем, какие параметры можно указывать несколько раз;
- вручную разбирать составные (композитные) аннотации.
Библиотека annotations решает эти задачи. Вы описываете аннотацию обычным классом OneScript с конструктором ПриСозданииОбъекта, а библиотека:
- регистрирует определение аннотации в контейнере;
- проверяет корректность применённых аннотаций (обязательные параметры, повторяемость, наличие неизвестных параметров);
- «разворачивает» аннотации, подставляя значения по умолчанию и раскрывая мета-аннотации;
- создаёт по данным аннотации готовый объект-экземпляр класса аннотации.
Основные понятия
| Понятие | Описание |
|---|---|
| Класс аннотации | Обычный класс OneScript, конструктор которого помечен &Аннотация("Имя"). Параметры конструктора становятся параметрами аннотации. |
ОпределениеАннотации | Метаданные аннотации: имя, тип, описание параметров и значений по умолчанию. |
КонтейнерАннотаций | Реестр всех известных определений аннотаций. |
РазворачивательАннотаций | Обрабатывает «сырые» аннотации: проверяет их, подставляет значения по умолчанию и раскрывает мета-аннотации. |
РаботаСАннотациями | Модуль-помощник для поиска аннотаций и чтения их параметров. |
&Повторяемый | Помечает параметр, который можно указывать несколько раз. |
&ПсевдонимДля | Объявляет параметр псевдонимом для параметра вложенной мета-аннотации (композитные аннотации). |
Примеры использования
1. Описание простой аннотации
Аннотация — это класс, конструктор которого помечен базовой аннотацией &Аннотация с именем будущей аннотации. Параметры конструктора становятся параметрами аннотации.
// Файл: АннотацияТестоваяАннотация.os
Перем УстановленноеЗначение Экспорт;
&Аннотация("ТестоваяАннотация")
Процедура ПриСозданииОбъекта(Значение)
УстановленноеЗначение = Значение;
КонецПроцедурыТеперь аннотацию &ТестоваяАннотация можно применять к методам, свойствам и параметрам других классов:
// Файл: ВладелецАннотаций.os
&ТестоваяАннотация("Привет")
Процедура ОбработатьДанные() Экспорт
КонецПроцедуры
&Цель
Процедура СохранитьДанные() Экспорт
КонецПроцедуры2. Регистрация аннотации в контейнере
КонтейнерАннотаций — это реестр известных аннотаций. При создании в него автоматически добавляется базовая аннотация &Аннотация, остальные нужно зарегистрировать вручную.
КонтейнерАннотаций = Новый КонтейнерАннотаций();
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияТестоваяАннотация"));
ОпределениеАннотации = КонтейнерАннотаций.ПолучитьОпределениеАннотации("ТестоваяАннотация");
Сообщить(ОпределениеАннотации.Имя()); // ТестоваяАннотация
Сообщить(ОпределениеАннотации.ИмяТипаАннотации()); // АннотацияТестоваяАннотацияПовторная регистрация той же аннотации вызывает исключение. Чтобы переопределить аннотацию намеренно, передайте флаг ПереопределитьЕслиСуществует:
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияТестоваяАннотация"), Истина);3. Чтение аннотаций у класса
Для получения «сырых» аннотаций используется библиотека reflector. Модуль РаботаСАннотациями помогает найти нужные методы, свойства и аннотации.
Рефлектор = Новый Рефлектор();
ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Тип("ВладелецАннотаций"));
// Найти все методы, помеченные аннотацией &ТестоваяАннотация
Методы = РаботаСАннотациями.НайтиМетодыСАннотацией(ТаблицаМетодов, "ТестоваяАннотация");
Для Каждого Метод Из Методы Цикл
Аннотация = РаботаСАннотациями.НайтиАннотацию(Метод.Аннотации, "ТестоваяАннотация");
Значение = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(Аннотация, "Значение");
Сообщить(Метод.Имя + ": " + Значение);
КонецЦикла;Аналогично можно работать со свойствами:
Рефлектор = Новый Рефлектор();
ТаблицаСвойств = Рефлектор.ПолучитьТаблицуСвойств(Тип("ВладелецАннотаций"), Истина);
Аннотация = РаботаСАннотациями.ПолучитьАннотацию(ТаблицаСвойств[0], "ТестоваяАннотация");4. Разворачивание аннотаций и значения по умолчанию
«Сырые» аннотации содержат только явно переданные параметры. Чтобы выполнить проверку корректности и подставить значения по умолчанию, используется РазворачивательАннотаций.
// Файл: АннотацияЦель.os
Перем УстановленноеЗначение Экспорт;
&Аннотация("Цель")
Процедура ПриСозданииОбъекта(Значение = "значение по умолчанию")
УстановленноеЗначение = Значение;
КонецПроцедурыКонтейнерАннотаций = Новый КонтейнерАннотаций();
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияЦель"));
Рефлектор = Новый Рефлектор();
ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Тип("ВладелецАннотаций"));
Метод = ТаблицаМетодов.Найти("СохранитьДанные", "Имя");
РазворачивательАннотаций = КонтейнерАннотаций.ПолучитьРазворачивательАннотаций();
РазворачивательАннотаций.РазвернутьАннотацииСвойства(Метод, Тип("ВладелецАннотаций"));При разворачивании выполняется проверка: если у обязательного параметра нет значения, передан неизвестный параметр или параметр без пометки &Повторяемый указан несколько раз — будет выброшено исключение с понятным текстом.
5. Создание объекта аннотации
По данным развёрнутой аннотации можно создать готовый экземпляр класса аннотации — со всеми подставленными значениями по умолчанию.
ЦельАннотация = РаботаСАннотациями.НайтиАннотацию(Метод.Аннотации, "Цель");
ОбъектЦели = КонтейнерАннотаций
.ПолучитьОпределениеАннотации("Цель")
.СоздатьОбъектАннотации(ЦельАннотация);
Сообщить(ОбъектЦели.УстановленноеЗначение); // значение по умолчанию6. Повторяемые параметры
Если параметр можно указывать несколько раз, пометьте его аннотацией &Повторяемый. Иначе несколько значений приведут к ошибке при разворачивании.
// Файл: АннотацияЦельПовторяемая.os
Перем УстановленныеЗначения Экспорт;
&Аннотация("ЦельПовторяемая")
Процедура ПриСозданииОбъекта(&Повторяемый Значение)
УстановленныеЗначения = Значение;
КонецПроцедуры&ЦельПовторяемая(Значение = "первое", Значение = "второе")
Процедура МетодСНесколькимиЗначениями() Экспорт
КонецПроцедурыДля чтения всех значений повторяемого параметра используйте ПолучитьЗначенияПараметровАннотации:
Значения = РаботаСАннотациями.ПолучитьЗначенияПараметровАннотации(Аннотация, "Значение");
// Значения = ["первое", "второе"]7. Композитные (мета-)аннотации
Аннотация может агрегировать другие аннотации. Для этого над её конструктором указываются нужные мета-аннотации, а параметры помечаются &ПсевдонимДля — значение такого параметра переносится в параметр указанной мета-аннотации.
// Файл: АннотацияКомпозит.os
&Аннотация("Композит")
&Цель
Процедура ПриСозданииОбъекта(
&ПсевдонимДля(Аннотация = "Цель", Параметр = "Значение") Значение = "значение композита по умолчанию"
)
КонецПроцедурыПрименение &Композит("переданное значение") при разворачивании раскроется в &Композит("переданное значение") + &Цель(Значение = "переданное значение").
&Композит("переданное значение")
Процедура МетодСКомпозитом() Экспорт
КонецПроцедурыКонтейнерАннотаций = Новый КонтейнерАннотаций();
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияЦель"));
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияКомпозит"));
Рефлектор = Новый Рефлектор();
ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Тип("ВладелецАннотаций"));
Метод = ТаблицаМетодов.Найти("МетодСКомпозитом", "Имя");
РазворачивательАннотаций = КонтейнерАннотаций.ПолучитьРазворачивательАннотаций();
РазворачивательАннотаций.РазвернутьАннотацииСвойства(Метод, Тип("ВладелецАннотаций"));
ЦельАннотация = РаботаСАннотациями.НайтиАннотацию(Метод.Аннотации, "Цель");
Значение = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(ЦельАннотация, "Значение");
Сообщить(Значение); // переданное значениеNOTE
По умолчанию в мета-аннотацию переносится только явно переданное значение параметра-псевдонима. Если значение не указано, мета-аннотация использует собственное значение по умолчанию. Чтобы переносить и значение по умолчанию псевдонима, укажите ПереноситьЗначениеПоУмолчанию = Истина в &ПсевдонимДля.
Параметр-псевдоним можно одновременно пометить &Повторяемый — тогда в целевую мета-аннотацию переносятся все переданные значения:
&Аннотация("КомпозитПовторяемый")
&ЦельПовторяемая
Процедура ПриСозданииОбъекта(
&Повторяемый &ПсевдонимДля(Аннотация = "ЦельПовторяемая", Параметр = "Значение") Значение
)
КонецПроцедурыТиповой сценарий применения
Библиотека удобна для построения декларативных механизмов: систем плагинов, маршрутизации команд, валидации, внедрения зависимостей и т. п. Общая схема работы:
- Описать классы-аннотации с нужными параметрами.
- Создать
КонтейнерАннотацийи зарегистрировать в нём все аннотации. - С помощью
reflectorполучить методы/свойства интересующих классов. - Развернуть аннотации
РазворачивателемАннотаций. - Прочитать параметры через
РаботаСАннотациямиили создать объекты аннотаций методомСоздатьОбъектАннотациии использовать их в своей логике.
