При разработке функционала в 1С:Предприятии 8.3, особенно при работе с динамическими списками или отчетами, часто возникает необходимость хранить ссылки на различные объекты метаданных в программно создаваемых структурах, таких как таблицы значений (ТЗ). Одной из таких задач является создание колонки ТЗ, которая должна содержать ссылку на роль. Однако, прямая попытка описать тип колонки как Метаданные.Роли приводит к ошибке, поскольку конструктор ОписаниеТипов не поддерживает такой подход. В этом материале мы подробно разберем, почему возникает такая ошибка, и какие существуют надежные способы решения этой задачи, включая лучшие практики.
Давайте проанализируем исходную проблему. Когда вы пытаетесь использовать код вида:
ТТ = ОписаниеТипов("Метаданные.Роли");
вы сталкиваетесь с ошибкой. Причина заключается в том, что ОписаниеТипов не предназначен для непосредственного описания конкретных классов метаданных как типов данных для хранения в базе или в динамических коллекциях, передаваемых между клиентом и сервером. Объекты метаданных (такие как сами роли, справочники, документы как структуры) являются служебными объектами платформы, описывающими структуру конфигурации, но не являются типами, которые можно напрямую присвоить колонке таблицы значений для постоянного хранения или безопасной передачи.
Единственный «общий» тип, который может быть связан с объектами метаданных в памяти, это ОбъектМетаданных. Однако и он имеет серьезные ограничения:
ОбъектМетаданных существует только в контексте выполнения, и его нельзя использовать для описания колонок таблицы значений, если эта ТЗ предназначена для сохранения в базу данных или передачи между клиентом и сервером.Исходя из этих ограничений, нам потребуются другие подходы для хранения ссылок на роли.
Один из самых простых и часто используемых способов — это хранение полного строкового имени роли. Этот подход достаточно гибок и не требует использования дополнительных справочников, если в вашей конфигурации не используется Библиотека стандартных подсистем (БСП).
Для создания колонки, предназначенной для хранения имени роли, мы описываем ее как строковый тип:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("ИмяРоли", Новый ОписаниеТипов("Строка"));
В этом случае, в каждую ячейку колонки ИмяРоли мы будем записывать полное имя роли, например, "Администратор", "Бухгалтер" и так далее.
Если вам нужно предоставить пользователю возможность выбора роли из списка, мы можем программно сформировать этот список. Поскольку коллекция Метаданные.Роли доступна только на сервере, нам потребуется выполнять действия по формированию списка на сервере.
СписокЗначений (где значением будет имя роли, а представлением — синоним) можно передать на клиент, если это необходимо для интерактивного выбора.Пример формирования списка ролей:
// Серверная функция
Функция ПолучитьСписокРолей()
СписокРолей = Новый СписокЗначений;
Для Каждого РольМетаданных Из Метаданные.Роли Цикл
СписокРолей.Добавить(РольМетаданных.Имя, РольМетаданных.Синоним);
КонецЦикла;
Возврат СписокРолей;
КонецФункции
// Клиентский код (или серверный, если выбор происходит на сервере)
// Предполагаем, что СписокРолей уже получен с сервера
// ...
// Пример использования для заполнения элемента формы, например, поля выбора:
// Элементы.ПолеВыбораРоли.СписокВыбора = ПолучитьСписокРолей();
// ...
Преимущества:
Недостатки:
Метаданные.Роли доступен только на сервере. Если вам нужен интерактивный выбор на клиенте, вам придется заранее формировать и передавать список имен или использовать серверные вызовы.Этот подход является наиболее надежным и рекомендуемым, если в вашей конфигурации используется Библиотека стандартных подсистем (БСП). БСП предоставляет специализированный справочник ИдентификаторыОбъектовМетаданных, который предназначен для хранения ссылок на объекты метаданных конфигурации.
Для хранения ссылки на роль в ТЗ мы указываем тип колонки как ссылку на соответствующий справочник:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("СсылкаНаРоль", Новый ОписаниеТипов("СправочникСсылка.ИдентификаторыОбъектовМетаданных"));
Теперь в эту колонку мы можем записывать ссылки на элементы справочника ИдентификаторыОбъектовМетаданных, которые соответствуют нужным ролям.
Для программного выбора ролей или работы с ними через этот справочник:
ОбщегоНазначенияБСП.ОбъектМетаданныхПоИмени() или запросы к справочнику ИдентификаторыОбъектовМетаданных).ПолноеИмя, чтобы показывать только элементы, начинающиеся с "Роль.".
// Пример получения ссылки на идентификатор роли
// Предполагаем, что у вас есть общий модуль ОбщегоНазначенияБСП или аналог
// Вариант 1: Использование БСП-функции (если доступна)
ИдентификаторРоли = ОбщегоНазначенияБСП.ОбъектМетаданныхПоИмени("Роль.Администратор");
// Вариант 2: Запрос к справочнику
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ИдентификаторыОбъектовМетаданных.Ссылка
|ИЗ
| Справочник.ИдентификаторыОбъектовМетаданных КАК ИдентификаторыОбъектовМетаданных
|ГДЕ
| ИдентификаторыОбъектовМетаданных.ПолноеИмя = &ПолноеИмя";
Запрос.УстановитьПараметр("ПолноеИмя", "Роль.Администратор");
РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
ИдентификаторРоли = Выборка.Ссылка;
КонецЕсли;
// Добавляем в ТЗ
// ТЗ.Добавить().СсылкаНаРоль = ИдентификаторРоли;
Важный нюанс при использовании справочника ИдентификаторыОбъектовМетаданных связан с расширениями конфигурации. В системе 1С может возникнуть ситуация, когда один и тот же объект метаданных (например, роль) присутствует как в основной конфигурации, так и в расширении. БСП обрабатывает такие ситуации, используя два разных справочника идентификаторов:
Справочник.ИдентификаторыОбъектовМетаданных — для объектов основной конфигурации.Справочник.ИдентификаторыОбъектовРасширений — для объектов, добавленных или измененных через расширения.Эта коллизия может привести к проблемам, если ваш программный код ищет роль только в основном справочнике, игнорируя расширения. В таком случае, роль, добавленная или модифицированная расширением, не будет найдена, что может привести к некорректному применению прав доступа или ошибкам в динамических алгоритмах. При работе с идентификаторами метаданных в расширенных конфигурациях всегда следует учитывать оба справочника или использовать универсальные функции БСП, которые умеют работать с объектами из расширений.
Преимущества:
Недостатки:
ИдентификаторыОбъектовРасширений и возможных "двойников".Если вам требуется хранить не одну, а несколько ролей в одной ячейке таблицы значений (например, для описания набора ролей, необходимых для определенного действия), мы сталкиваемся с тем, что ОписаниеТипов не позволяет создать тип колонки "МассивРолей". В таких случаях мы можем использовать следующие подходы:
ТЗ.Колонки.Добавить("НаборРолей", Новый ОписаниеТипов("Строка"));
// ...
// Запись: "Администратор,Бухгалтер,Менеджер"
ИдентификаторыОбъектовМетаданных или массив строк с именами ролей, можно использовать тип ХранилищеЗначения. Этот тип позволяет сериализовать и хранить в базе данных произвольные значения 1С, включая массивы, структуры и коллекции.
ТЗ.Колонки.Добавить("НаборРолейОбъектом", Новый ОписаниеТипов("ХранилищеЗначения"));
// ...
// Создаем массив, который будет храниться в ХранилищеЗначения
МассивРолейДляХранения = Новый Массив;
МассивРолейДляХранения.Добавить(ИдентификаторРолиАдминистратор);
МассивРолейДляХранения.Добавить(ИдентификаторРолиБухгалтер);
// Записываем в колонку
// ТЗ.Добавить().НаборРолейОбъектом = Новый ХранилищеЗначения(МассивРолейДляХранения);
При использовании ХранилищеЗначения помните, что для получения исходного значения из него потребуется выполнить операцию "получить".
Исходя из рассмотренных подходов, мы можем сформулировать следующие рекомендации:
Метаданные.Роли: Ни при каких обстоятельствах не пытайтесь использовать ОписаниеТипов("Метаданные.Роли") или напрямую передавать объекты Метаданные.Роли через клиент-серверные границы. Это приведет к ошибкам и ненадежной работе.СправочникСсылка.ИдентификаторыОбъектовМетаданных: Если у вас есть БСП, это самый надежный и рекомендуемый способ хранения ссылок на роли. Он обеспечивает стабильность и целостность данных. Не забывайте о возможности ИдентификаторыОбъектовРасширений.Метаданные доступна только на сервере. Формирование списков для выбора на клиенте должно производиться на сервере с последующей передачей безопасных для клиента типов данных (строки, списки значений, ссылки на справочники).Правильный выбор подхода зависит от требований к надежности, масштабируемости и используемых в конфигурации подсистем. Мы всегда рекомендуем придерживаться стандартных механизмов платформы и библиотек, таких как БСП, для обеспечения устойчивости и простоты поддержки вашей системы.