При разработке универсальных механизмов, обработок по переносу данных или динамическом формировании интерфейса часто возникает задача: имея объект метаданных (ОбъектМетаданных), получить соответствующий ему системный тип данных (например, СправочникСсылка.Номенклатура) или создать пустую ссылку. Разберем основные способы реализации этой задачи, а также типичные ошибки и нюансы платформы 1С:Предприятие.
У любого ссылочного объекта конфигурации (справочники, документы, планы видов характеристик и др.) в метаданных присутствует стандартный реквизит Ссылка. Проанализируем, как с его помощью можно получить тип или пустое ссылочное значение.
Свойство Тип стандартного реквизита возвращает объект ОписаниеТипов. Чтобы получить само значение системного типа Тип, обратимся к массиву типов описания, а для получения значения по умолчанию (пустой ссылки) воспользуемся методом ПривестиЗначение():
// Получение типа ссылки
ТипСсылки = ОбъектМетаданных.СтандартныеРеквизиты.Ссылка.Тип.Типы()[0];
// Получение пустой ссылки
ПустаяСсылка = ОбъектМетаданных.СтандартныеРеквизиты.Ссылка.Тип.ПривестиЗначение();
Важное ограничение: прямое обращение вида ОбъектМетаданных.СтандартныеРеквизиты.Ссылка вызывает ошибку выполнения («Поле объекта не обнаружено») для нессылочных объектов метаданных (константы, регистры, отчеты, обработки). Чтобы код работал универсально, предварительно проверим наличие реквизита:
РеквизитСсылка = ОбъектМетаданных.СтандартныеРеквизиты.Найти("Ссылка");
Если РеквизитСсылка <> Неопределено Тогда
ТипСсылки = РеквизитСсылка.Тип.Типы()[0];
ПустаяСсылка = РеквизитСсылка.Тип.ПривестиЗначение();
КонецЕсли;
Разберем строковый подход. В платформе 1С системная функция Тип() принимает на вход строковое имя типа, например, "СправочникСсылка.Номенклатура" или "ДокументСсылка.РеализацияТоваровУслуг".
Если мы обходим коллекцию конкретного вида метаданных, сформируем имя типа конкатенацией:
// Для справочников:
ТипСсылки = Тип("СправочникСсылка." + ОбъектМетаданных.Имя);
// Для документов:
ТипСсылки = Тип("ДокументСсылка." + ОбъектМетаданных.Имя);
Рассмотрим более универсальный вариант, подходящий для любого ссылочного объекта (планы счетов, перечисления, задачи, бизнес-процессы). Метод ПолноеИмя() возвращает строку вида Справочник.Номенклатура. Добавим суффикс Ссылка. с помощью функции СтрЗаменить():
ПолноеИмяОбъекта = ОбъектМетаданных.ПолноеИмя(); // "Справочник.Номенклатура"
ИмяТипа = СтрЗаменить(ПолноеИмяОбъекта, ".", "Ссылка."); // "СправочникСсылка.Номенклатура"
ТипСсылки = Тип(ИмяТипа);
Посмотрим на практический пример получения типа через обращение к менеджеру прикладного объекта. Менеджеры ссылочных типов содержат метод ПустаяСсылка(), который возвращает экземпляр пустой ссылки. Далее с помощью функции ТипЗнч() получаем сам тип:
// Получаем пустую ссылку через менеджер справочника
ПустаяСсылка = Справочники[ОбъектМетаданных.Имя].ПустаяСсылка();
// Получаем системный тип значения
ТипСсылки = ТипЗнч(ПустаяСсылка);
Обратите внимание на разницу функций: функция Тип() ожидает исключительно строковое представление типа (например, Тип("СправочникСсылка.Номенклатура")). Передача в нее значения или пустой ссылки приведет к ошибке. Для получения типа из уже существующего значения всегда используем функцию ТипЗнч().
Если перед нами стоит обратная задача — по известному типу Тип или значению ссылки найти соответствующий объект метаданных, воспользуемся методом глобального контекста Метаданные.НайтиПоТипу():
// Поиск по объекту типа Тип
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипСсылки);
// Поиск по конкретному значению ссылки
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(СсылкаНаОбъект));
ОбъектМетаданных.СтандартныеРеквизиты.Ссылка.Тип.ПривестиЗначение() с предварительной проверкой на существование реквизита.Тип для сравнения или передачи в ОписаниеТипов — наиболее универсален способ с преобразованием полного имени Тип(СтрЗаменить(ОбъектМетаданных.ПолноеИмя(), ".", "Ссылка.")).Метаданные.Справочники) — оптимально использовать менеджер Справочники[ОбъектМетаданных.Имя].ПустаяСсылка().