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