Как получить имя объекта метаданных по типу значения из Плана видов характеристик в 1С

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

На практике программирования в среде 1С:Предприятие часто возникает задача динамического определения имени объекта метаданных (например, справочника, документа или перечисления) на основе типа значения, хранящегося в Плане видов характеристик (ПВХ). Это особенно актуально при разработке универсальных механизмов заполнения субконто в табличных частях документов, когда состав реквизитов и доступных типов зависит от выбранного счета учета или разреза аналитики.

Выясним причину, почему стандартные подходы иногда ставят разработчиков в тупик, и разберем наиболее эффективные, безопасные и быстрые способы решения этой задачи как для обычных, так и для управляемых форм.

Анализ распространенной ошибки: почему метод Новый() — это антипаттерн

Рассмотрим ситуацию, описанную в сообщении 11. Пытаясь получить имя метаданных из типа, разработчики часто прибегают к следующему алгоритму: создают пустую ссылку или объект через конструктор Новый(), а затем обращаются к его свойству Метаданные().Имя.

Проанализируем пример такого неоптимального кода:


Для каждого ТипДокумента Из Элемент.ТипЗначения.Типы() Цикл
    ДокументСсылка = Новый(ТипДокумента); // Опасный участок кода!
    Имя = ДокументСсылка.Метаданные().Имя;
    Синоним = ДокументСсылка.Метаданные().Синоним;
КонецЦикла;

Разберем по шагам, почему этот подход крайне нежелателен в профессиональной разработке:

  1. Избыточная нагрузка на систему. Конструктор Новый() инициализирует полноценный объект или ссылку в оперативной памяти. Если в цикле обрабатывается множество тяжелых объектов метаданных, это может привести к заметному снижению производительности приложения.
  2. Критическая уязвимость к примитивным типам. Если в описании типов вашего Плана видов характеристик окажется простой примитивный тип (например, Строка, Число, Дата или Булево), вызов Новый(Тип) мгновенно вызовет аварийное завершение работы программы с ошибкой выполнения, так как для простых типов невозможно создать объектную ссылку таким способом.

Правильное решение: использование метода Метаданные.НайтиПоТипу()

Для быстрого и безопасного получения метаданных платформа 1С предоставляет специализированный глобальный метод — Метаданные.НайтиПоТипу(). Он работает со структурами метаданных конфигурации напрямую, минуя создание экземпляров объектов в памяти.

Посмотрим на пример правильной реализации обхода типов ПВХ без создания пустых ссылок:


// Получаем описание типов из реквизита ПланаВидовХарактеристик
ОписаниеТиповПВХ = ПВХЗначение.ТипЗначения;

// Извлекаем массив всех доступных типов
МассивТипов = ОписаниеТиповПВХ.Типы();

Для Каждого ТекТип Из МассивТипов Цикл
    
    // Ищем объект метаданных напрямую по типу базы данных
    ОбъектМетаданных = Метаданные.НайтиПоТипу(ТекТип);
    
    // Проверяем, что полученный тип не является примитивным
    Если ОбъектМетаданных <> Неопределено Тогда
        
        // Получаем необходимые свойства объекта метаданных
        ИмяОбъекта       = ОбъектМетаданных.Имя;         // Например: "Контрагенты"
        СинонимОбъекта   = ОбъектМетаданных.Синоним;     // Например: "Контрагенты"
        ПолноеИмяОбъекта = ОбъектМетаданных.ПолноеИмя(); // Например: "Справочник.Контрагенты"
        
        // Выполняем сопоставление или заполнение данных
        // ...
        
    Иначе
        // Сюда код попадает, если ТекТип — это Строка, Число, Дата или Булево
        Сообщить("Тип " + Строка(ТекТип) + " является примитивным. Метаданные отсутствуют.");
    EndЕсли;
    
КонецЦикла;

Как гарантированно определить, что тип является именно «Перечислением»?

Часто в Планах видов характеристик разработчику нужно отсечь справочники и документы, оставив для обработки только перечисления. Рассмотрим два надежных способа классификации типа после получения объекта метаданных.

Способ 1. Строковая проверка через полное имя

Метод ПолноеИмя() у любого перечисления всегда возвращает строку, начинающуюся с префикса "Перечисление.". Мы можем легко проверить это с помощью строковых функций платформы:


Если Лев(ОбъектМетаданных.ПолноеИмя(), 14) = "Перечисление." Тогда
    // Мы точно определили, что данный тип относится к перечислениям конфигурации
    ИмяПеречисления = ОбъектМетаданных.Имя;
КонецЕсли;

Способ 2. Использование метода СодержитТип()

Этот способ является более академичным и строгим, так как работает непосредственно со структурами типов платформы и исключает любые ошибки ручного разбора строк:


Если Перечисления.ТипВсеСсылки().СодержитТип(ТекТип) Тогда
    // Перед нами перечисление
ИначеЕсли Справочники.ТипВсеСсылки().СодержитТип(ТекТип) Тогда
    // Перед нами справочник
ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТекТип) Тогда
    // Перед нами документ
КонецЕсли;

Использование готовых механизмов Библиотеки стандартных подсистем (БСП)

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

Обратите внимание на полезные функции общего модуля ОбщегоНазначения:

Проанализируем пример использования готового функционала БСП:


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

Использование связки стандартных методов платформы 1С или готовых функций БСП гарантирует высокую отказоустойчивость вашего кода, быструю обработку данных и отсутствие утечек памяти при работе со сложными структурами метаданных конфигурации.

← На главную