К статье
Практический материал

Разработка и Конфигурация · 12 мин

1С: как получить тип объекта метаданных

Как в 1С получить тип объекта метаданных: Метаданные.НайтиПоТипу, ТипЗнч, работа с объектом Метаданные. Разбор методов, примеры кода, типичные ошибки.

Во встроенном языке 1С часто встречается задача: по ссылке или объекту определить, к какому виду метаданных он относится — справочник это, документ, план видов характеристик или что-то ещё. Такая проверка нужна в универсальных обработках, обменах данными, подписках на события и при написании общих процедур, которые должны работать с разными типами объектов.

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

Разберём рабочие приёмы с примерами кода, ограничения каждого метода и типичные ошибки, из-за которых универсальные механизмы начинают падать или возвращать неожиданные результаты.

Разница между типом значения и объектом метаданных

Прежде чем писать код, важно различать два понятия, которые часто путают. Тип значения — это тип данных конкретной переменной: «СправочникСсылка.Номенклатура», «ДокументОбъект.РеализацияТоваровУслуг», «Число», «Строка». Его возвращает функция ТипЗнч(), и результат имеет тип «Тип».

Объект метаданных — это описание элемента конфигурации: конкретного справочника, документа, регистра. Он содержит имя, синоним, состав реквизитов, табличных частей и другую структурную информацию. Один объект метаданных может соответствовать нескольким типам значений: например, справочнику «Номенклатура» соответствуют типы «СправочникСсылка.Номенклатура», «СправочникОбъект.Номенклатура», «СправочникВыборка.Номенклатура» и другие.

Поэтому формулировка «получить тип объекта метаданных» на практике означает одну из трёх задач: определить тип значения переменной, найти объект метаданных по значению или по типу, либо получить метаданные напрямую от ссылки. Ниже разобраны все три сценария.

Получение типа значения через ТипЗнч()

Функция ТипЗнч(Значение) возвращает тип переданного значения. Это самый простой способ понять, что лежит в переменной, когда процедура принимает параметры произвольного типа.

ТипЗначения = ТипЗнч(Параметр);

Если ТипЗначения = Тип("СправочникСсылка.Номенклатура") Тогда

// работаем с номенклатурой

КонецЕсли;

Функция Тип("ИмяТипа") создаёт значение типа «Тип» по строковому имени. Имя строится по шаблону: вид объекта, точка, имя объекта метаданных — например, «ДокументСсылка.ПоступлениеТоваровУслуг». Для примитивных типов используются имена «Число», «Строка», «Дата», «Булево».

Учтите: сравнение типов выполняется строго. Тип «СправочникСсылка.Номенклатура» не равен типу «СправочникОбъект.Номенклатура», хотя оба относятся к одному объекту метаданных. Если процедура должна принимать и ссылку, и объект, проверяйте оба варианта или работайте на уровне метаданных.

Поиск объекта метаданных по типу: Метаданные.НайтиПоТипу()

Метод Метаданные.НайтиПоТипу(Тип) возвращает объект описания метаданного, которому соответствует переданный тип, или Неопределено, если соответствия нет. В связке с ТипЗнч() это основной приём для универсальных механизмов.

ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(Ссылка));

Если ОбъектМетаданных = Неопределено Тогда

ВызватьИсключение "Не удалось определить метаданные для значения";

КонецЕсли;

ИмяОбъекта = ОбъектМетаданных.Имя; // "Номенклатура"

ПолноеИмя = ОбъектМетаданных.ПолноеИмя(); // "Справочник.Номенклатура"

Синоним = ОбъектМетаданных.Синоним; // представление для пользователя

Определив полное имя, легко выяснить вид объекта — достаточно взять часть строки до первой точки. Альтернатива — проверка через коллекции метаданных:

Если Метаданные.Справочники.Содержит(ОбъектМетаданных) Тогда

// это справочник

ИначеЕсли Метаданные.Документы.Содержит(ОбъектМетаданных) Тогда

// это документ

КонецЕсли;

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

bsl
Функция ВидОбъектаПоСсылке(Ссылка) Экспорт
    Мета = Ссылка.Метаданные();
    ПолноеИмя = Мета.ПолноеИмя();
    Возврат СтрРазделить(ПолноеИмя, ".")[0]; // "Справочник", "Документ" и т.д.
КонецФункции

Получение метаданных напрямую от ссылки или объекта

У ссылок и объектов данных есть метод Метаданные(), который сразу возвращает объект описания метаданного без промежуточного вызова ТипЗнч(). Это короче и надёжнее, когда на входе гарантированно ссылочное значение.

МетаДокумента = ДокументСсылка.Метаданные();

Сообщить(МетаДокумента.Имя); // имя документа

Сообщить(МетаДокумента.ДлинаНомера); // свойства объекта метаданных

Для пустой ссылки метод тоже работает корректно: метаданные определяются по типу ссылки, а не по данным информационной базы. Это удобно, когда нужно проверить вид ещё не заполненного реквизита.

Обратная задача — получить тип по объекту метаданных — решается конструкцией Тип("СправочникСсылка." + Метаданные.Имя) или через менеджер объекта. Например, для справочника менеджер доступен как Справочники[Мета.Имя], а тип ссылки формируется по известному шаблону имени.

Определение вида объекта в запросах и через XMLType

В языке запросов тип значения проверяется оператором ССЫЛКА и функцией ТИПЗНАЧЕНИЯ(). Это полезно, когда нужно отфильтровать составной реквизит по виду объекта прямо в запросе, не выгружая данные в код.

ВЫБРАТЬ

ХозрасчетныйОстатки.Субконто1 КАК Субконто

ИЗ РегистрБухгалтерии.Хозрасчетный.Остатки КАК ХозрасчетныйОстатки

ГДЕ ХозрасчетныйОстатки.Субконто1 ССЫЛКА Справочник.Номенклатура

Для сценариев обмена и сериализации существует функция XMLТипЗнч(), возвращающая описание типа в терминах XML-схем. Она применяется в механизмах XDTO и веб-сервисов, где имена типов должны соответствовать пространствам имён пакетов, а не внутренним именам платформы.

Сравнение способов

ТипЗнч(Значение)

Подходит для проверки типа любого значения, включая примитивные. Не даёт информации о структуре объекта конфигурации.

Метаданные.НайтиПоТипу()

Возвращает полное описание метаданного по типу. Для примитивных типов вернёт Неопределено.

Ссылка.Метаданные()

Самый короткий путь для ссылочных значений. Не работает с числами, строками и Неопределено.

Проверка ССЫЛКА в запросе

Фильтрация по виду объекта на уровне СУБД без выборки лишних данных. Требует заранее знать проверяемый вид.

Практический пример: универсальная функция определения вида объекта

Соберём перечисленные приёмы в функцию, которая безопасно определяет вид объекта для значения любого типа и не падает на примитивных данных и Неопределено.

Функция ОпределитьВидОбъекта(Значение) Экспорт

Если Значение = Неопределено Тогда

Возврат "Неопределено";

КонецЕсли;

ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(Значение));

Если ОбъектМетаданных = Неопределено Тогда

// примитивный тип или значение без метаданных

Возврат Строка(ТипЗнч(Значение));

КонецЕсли;

ЧастиИмени = СтрРазделить(ОбъектМетаданных.ПолноеИмя(), ".");

Возврат ЧастиИмени[0]; // вид: Справочник, Документ, РегистрСведений...

КонецФункции

Такая функция удобна в подписках на события «ПриЗаписи», где источником может быть объект любого вида, а также в обработках заполнения табличных частей и механизмах логирования, где требуется человекочитаемое описание переданного значения.

Порядок действий при определении метаданных по значению
  1. 1
    Проверьте значение на Неопределено, чтобы избежать ложных результатов
  2. 2
    Вызовите Метаданные.НайтиПоТипу(ТипЗнч(Значение))
  3. 3
    Обработайте случай, когда метод вернул Неопределено (примитивный тип)
  4. 4
    Получите ПолноеИмя() и при необходимости разберите его на вид и имя объекта
  5. 5
    Проверьте результат на тестовых значениях каждого ожидаемого вида

Типичные ошибки и ограничения

Самая частая ошибка — ожидание, что НайтиПоТипу() вернёт метаданные для любого значения. Для чисел, строк, дат и значения Неопределено метод всегда возвращает Неопределено, и обращение к свойствам результата без проверки приводит к ошибке выполнения.

Вторая группа ошибок связана со смешением ссылок и объектов. Код, рассчитанный на «СправочникСсылка», ломается, когда в подписку на событие приходит «СправочникОбъект». Универсальные механизмы следует строить на уровне метаданных, а не конкретных типов значений.

Третий момент — производительность. Вызов НайтиПоТипу() внутри большого цикла обходится дороже, чем кажется. Если тип значений в цикле не меняется, определите метаданные один раз до цикла и переиспользуйте результат.

Типичные ошибки
01
Обращение к свойствам результата НайтиПоТипу() без проверки на Неопределено — ошибка выполнения на примитивных типах
02
Сравнение типа только с Ссылка-вариантом — код не срабатывает для Объект-варианта того же метаданного
03
Разбор ПолноеИмя() через Найти() вместо СтрРазделить() — хрупкий код, чувствительный к формату строки
04
Вызов НайтиПоТипу() в каждой итерации цикла при неизменном типе — лишняя нагрузка

Проверка результата и отладка

Убедиться, что механизм определения вида работает правильно, можно через табло или журнал регистрации. Выведите для тестового набора значений три величины: строковое представление типа, полное имя метаданных и вид объекта. Для каждого вида объектов конфигурации результат должен быть стабильным и предсказуемым.

При отладке в конфигураторе удобно смотреть значение ТипЗнч(Переменная) в табло: платформа покажет тип в читаемом виде. Для ссылок дополнительно доступно свойство УникальныйИдентификатор(), которое помогает отличить «битую» ссылку с корректным типом от нормального значения — тип у битой ссылки определяется правильно, а вот обращение к реквизитам вернёт ошибку или пустые значения.

Контрольные точки

Как проверить результат

Результат НайтиПоТипу для ссылки на справочник
Норма

Объект метаданных с ПолноеИмя вида «Справочник.Имя»

Тревожный признак

Неопределено — значит, передан примитив или Неопределено

Поведение на пустой ссылке
Норма

Метаданные определяются корректно

Тревожный признак

Ошибка обращения к метаданным — проверьте, что значение ссылочного типа

Работа в подписке на событие
Норма

Вид определяется для Источника любого вида

Тревожный признак

Код падает на объектах — проверяются только типы ссылок

Часто задаваемые вопросы

Чем отличается ТипЗнч() от Метаданные.НайтиПоТипу()?

ТипЗнч() возвращает тип конкретного значения — например, «ДокументСсылка.РеализацияТоваровУслуг». НайтиПоТипу() по этому типу находит описание метаданного — сам документ «Реализация товаров услуг» с его реквизитами и свойствами. Первая функция отвечает на вопрос «что за значение», вторая — «как устроен соответствующий объект конфигурации».

Почему НайтиПоТипу() возвращает Неопределено?

Метод возвращает Неопределено, если типу не соответствует ни один объект метаданных. Так происходит с примитивными типами (число, строка, дата), со значением Неопределено и с типами, не связанными с объектами конфигурации. Всегда проверяйте результат перед обращением к его свойствам.

Как узнать вид объекта, если есть только строка с полным именем?

Используйте Метаданные.НайтиПоПолномуИмени("Справочник.Номенклатура") — метод вернёт объект метаданных или Неопределено, если такого объекта нет. Вид объекта получают разбором строки до первой точки через СтрРазделить().

Можно ли определить вид объекта в запросе без кода?

Да, через оператор ССЫЛКА в условии ГДЕ или через функцию ТИПЗНАЧЕНИЯ() в сочетании с ВЫБОР...КОГДА. Это позволяет классифицировать значения составных реквизитов прямо в выборке, не перебирая их в коде.

Как получить тип ссылки по объекту метаданных?

Сформируйте имя типа по шаблону: вид объекта плюс «Ссылка» плюс имя метаданного, например Тип("СправочникСсылка." + Мета.Имя). Шаблон зависит от вида: для документов это «ДокументСсылка», для планов счетов — «ПланСчетовСсылка» и так далее.

Работает ли определение метаданных для внешних обработок?

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

Итог

Что важно запомнить

Для определения вида объекта по значению используйте связку Метаданные.НайтиПоТипу(ТипЗнч(Значение)) с обязательной проверкой результата на Неопределено. Для ссылок короче вызвать Ссылка.Метаданные(). Вид объекта извлекается из ПолноеИмя() до первой точки, а в универсальных механизмах надёжнее работать на уровне метаданных, а не конкретных типов значений.