Skip to content

annotations

Библиотека для работы с аннотациями как с объектами первого класса. Позволяет описывать параметры аннотаций и их значения, а также получать их в виде объектов. Поддерживает механизм мета-аннотаций (аннотаций-агрегаторов других аннотаций).

Публичный интерфейс библиотеки описан в разделе api.

Зачем это нужно

В OneScript аннотации (&ИмяАннотации) можно навешивать на методы, свойства и параметры конструктора. С помощью reflector их можно прочитать в виде таблицы значений, но «сырые» аннотации — это просто набор строк и нетипизированных параметров. Разработчику приходится самостоятельно:

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

Библиотека annotations решает эти задачи. Вы описываете аннотацию обычным классом OneScript с конструктором ПриСозданииОбъекта, а библиотека:

  • регистрирует определение аннотации в контейнере;
  • проверяет корректность применённых аннотаций (обязательные параметры, повторяемость, наличие неизвестных параметров);
  • «разворачивает» аннотации, подставляя значения по умолчанию и раскрывая мета-аннотации;
  • создаёт по данным аннотации готовый объект-экземпляр класса аннотации.

Основные понятия

ПонятиеОписание
Класс аннотацииОбычный класс OneScript, конструктор которого помечен &Аннотация("Имя"). Параметры конструктора становятся параметрами аннотации.
ОпределениеАннотацииМетаданные аннотации: имя, тип, описание параметров и значений по умолчанию.
КонтейнерАннотацийРеестр всех известных определений аннотаций.
РазворачивательАннотацийОбрабатывает «сырые» аннотации: проверяет их, подставляет значения по умолчанию и раскрывает мета-аннотации.
РаботаСАннотациямиМодуль-помощник для поиска аннотаций и чтения их параметров.
&ПовторяемыйПомечает параметр, который можно указывать несколько раз.
&ПсевдонимДляОбъявляет параметр псевдонимом для параметра вложенной мета-аннотации (композитные аннотации).

Примеры использования

1. Описание простой аннотации

Аннотация — это класс, конструктор которого помечен базовой аннотацией &Аннотация с именем будущей аннотации. Параметры конструктора становятся параметрами аннотации.

bsl
// Файл: АннотацияТестоваяАннотация.os

Перем УстановленноеЗначение Экспорт;

&Аннотация("ТестоваяАннотация")
Процедура ПриСозданииОбъекта(Значение)
    УстановленноеЗначение = Значение;
КонецПроцедуры

Теперь аннотацию &ТестоваяАннотация можно применять к методам, свойствам и параметрам других классов:

bsl
// Файл: ВладелецАннотаций.os

&ТестоваяАннотация("Привет")
Процедура ОбработатьДанные() Экспорт
КонецПроцедуры

&Цель
Процедура СохранитьДанные() Экспорт
КонецПроцедуры

2. Регистрация аннотации в контейнере

КонтейнерАннотаций — это реестр известных аннотаций. При создании в него автоматически добавляется базовая аннотация &Аннотация, остальные нужно зарегистрировать вручную.

bsl
КонтейнерАннотаций = Новый КонтейнерАннотаций();
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияТестоваяАннотация"));

ОпределениеАннотации = КонтейнерАннотаций.ПолучитьОпределениеАннотации("ТестоваяАннотация");

Сообщить(ОпределениеАннотации.Имя());              // ТестоваяАннотация
Сообщить(ОпределениеАннотации.ИмяТипаАннотации());  // АннотацияТестоваяАннотация

Повторная регистрация той же аннотации вызывает исключение. Чтобы переопределить аннотацию намеренно, передайте флаг ПереопределитьЕслиСуществует:

bsl
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияТестоваяАннотация"), Истина);

3. Чтение аннотаций у класса

Для получения «сырых» аннотаций используется библиотека reflector. Модуль РаботаСАннотациями помогает найти нужные методы, свойства и аннотации.

bsl
Рефлектор = Новый Рефлектор();
ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Тип("ВладелецАннотаций"));

// Найти все методы, помеченные аннотацией &ТестоваяАннотация
Методы = РаботаСАннотациями.НайтиМетодыСАннотацией(ТаблицаМетодов, "ТестоваяАннотация");

Для Каждого Метод Из Методы Цикл
    Аннотация = РаботаСАннотациями.НайтиАннотацию(Метод.Аннотации, "ТестоваяАннотация");
    Значение = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(Аннотация, "Значение");
    Сообщить(Метод.Имя + ": " + Значение);
КонецЦикла;

Аналогично можно работать со свойствами:

bsl
Рефлектор = Новый Рефлектор();
ТаблицаСвойств = Рефлектор.ПолучитьТаблицуСвойств(Тип("ВладелецАннотаций"), Истина);

Аннотация = РаботаСАннотациями.ПолучитьАннотацию(ТаблицаСвойств[0], "ТестоваяАннотация");

4. Разворачивание аннотаций и значения по умолчанию

«Сырые» аннотации содержат только явно переданные параметры. Чтобы выполнить проверку корректности и подставить значения по умолчанию, используется РазворачивательАннотаций.

bsl
// Файл: АннотацияЦель.os
Перем УстановленноеЗначение Экспорт;

&Аннотация("Цель")
Процедура ПриСозданииОбъекта(Значение = "значение по умолчанию")
    УстановленноеЗначение = Значение;
КонецПроцедуры
bsl
КонтейнерАннотаций = Новый КонтейнерАннотаций();
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияЦель"));

Рефлектор = Новый Рефлектор();
ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Тип("ВладелецАннотаций"));
Метод = ТаблицаМетодов.Найти("СохранитьДанные", "Имя");

РазворачивательАннотаций = КонтейнерАннотаций.ПолучитьРазворачивательАннотаций();
РазворачивательАннотаций.РазвернутьАннотацииСвойства(Метод, Тип("ВладелецАннотаций"));

При разворачивании выполняется проверка: если у обязательного параметра нет значения, передан неизвестный параметр или параметр без пометки &Повторяемый указан несколько раз — будет выброшено исключение с понятным текстом.

5. Создание объекта аннотации

По данным развёрнутой аннотации можно создать готовый экземпляр класса аннотации — со всеми подставленными значениями по умолчанию.

bsl
ЦельАннотация = РаботаСАннотациями.НайтиАннотацию(Метод.Аннотации, "Цель");

ОбъектЦели = КонтейнерАннотаций
    .ПолучитьОпределениеАннотации("Цель")
    .СоздатьОбъектАннотации(ЦельАннотация);

Сообщить(ОбъектЦели.УстановленноеЗначение); // значение по умолчанию

6. Повторяемые параметры

Если параметр можно указывать несколько раз, пометьте его аннотацией &Повторяемый. Иначе несколько значений приведут к ошибке при разворачивании.

bsl
// Файл: АннотацияЦельПовторяемая.os
Перем УстановленныеЗначения Экспорт;

&Аннотация("ЦельПовторяемая")
Процедура ПриСозданииОбъекта(&Повторяемый Значение)
    УстановленныеЗначения = Значение;
КонецПроцедуры
bsl
&ЦельПовторяемая(Значение = "первое", Значение = "второе")
Процедура МетодСНесколькимиЗначениями() Экспорт
КонецПроцедуры

Для чтения всех значений повторяемого параметра используйте ПолучитьЗначенияПараметровАннотации:

bsl
Значения = РаботаСАннотациями.ПолучитьЗначенияПараметровАннотации(Аннотация, "Значение");
// Значения = ["первое", "второе"]

7. Композитные (мета-)аннотации

Аннотация может агрегировать другие аннотации. Для этого над её конструктором указываются нужные мета-аннотации, а параметры помечаются &ПсевдонимДля — значение такого параметра переносится в параметр указанной мета-аннотации.

bsl
// Файл: АннотацияКомпозит.os

&Аннотация("Композит")
&Цель
Процедура ПриСозданииОбъекта(
    &ПсевдонимДля(Аннотация = "Цель", Параметр = "Значение") Значение = "значение композита по умолчанию"
)
КонецПроцедуры

Применение &Композит("переданное значение") при разворачивании раскроется в &Композит("переданное значение") + &Цель(Значение = "переданное значение").

bsl
&Композит("переданное значение")
Процедура МетодСКомпозитом() Экспорт
КонецПроцедуры
bsl
КонтейнерАннотаций = Новый КонтейнерАннотаций();
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияЦель"));
КонтейнерАннотаций.ДобавитьАннотацию(Тип("АннотацияКомпозит"));

Рефлектор = Новый Рефлектор();
ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Тип("ВладелецАннотаций"));
Метод = ТаблицаМетодов.Найти("МетодСКомпозитом", "Имя");

РазворачивательАннотаций = КонтейнерАннотаций.ПолучитьРазворачивательАннотаций();
РазворачивательАннотаций.РазвернутьАннотацииСвойства(Метод, Тип("ВладелецАннотаций"));

ЦельАннотация = РаботаСАннотациями.НайтиАннотацию(Метод.Аннотации, "Цель");
Значение = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(ЦельАннотация, "Значение");
Сообщить(Значение); // переданное значение

NOTE

По умолчанию в мета-аннотацию переносится только явно переданное значение параметра-псевдонима. Если значение не указано, мета-аннотация использует собственное значение по умолчанию. Чтобы переносить и значение по умолчанию псевдонима, укажите ПереноситьЗначениеПоУмолчанию = Истина в &ПсевдонимДля.

Параметр-псевдоним можно одновременно пометить &Повторяемый — тогда в целевую мета-аннотацию переносятся все переданные значения:

bsl
&Аннотация("КомпозитПовторяемый")
&ЦельПовторяемая
Процедура ПриСозданииОбъекта(
    &Повторяемый &ПсевдонимДля(Аннотация = "ЦельПовторяемая", Параметр = "Значение") Значение
)
КонецПроцедуры

Типовой сценарий применения

Библиотека удобна для построения декларативных механизмов: систем плагинов, маршрутизации команд, валидации, внедрения зависимостей и т. п. Общая схема работы:

  1. Описать классы-аннотации с нужными параметрами.
  2. Создать КонтейнерАннотаций и зарегистрировать в нём все аннотации.
  3. С помощью reflector получить методы/свойства интересующих классов.
  4. Развернуть аннотации РазворачивателемАннотаций.
  5. Прочитать параметры через РаботаСАннотациями или создать объекты аннотаций методом СоздатьОбъектАннотации и использовать их в своей логике.