Как в 1С получить ссылку на объект по объекту метаданных и уникальному идентификатору (GUID)?

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

В практике разработки на платформе 1С:Предприятие 8 довольно часто возникает задача универсального получения ссылки на элемент данных (будь то справочник, документ, план видов характеристик или другой объект), когда в распоряжении программиста есть только объект метаданных (ОбъектМетаданных) или его полное имя, а также УникальныйИдентификатор (GUID) этой ссылки. Такая необходимость регулярно появляется при создании универсальных механизмов обмена данными, обработок импорта, разборе технологических журналов или логов регистрации, а также при работе с навигационными ссылками.

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


Способ 1. Получение ссылки для конкретного класса метаданных (частный случай)

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

Проанализируем этот пример:


// Предположим, у нас есть имя справочника и GUID в виде строки или объекта
ИмяСправочника = "Организации";
НовыйGUID = Новый УникальныйИдентификатор("88d54406-36a1-11e9-8bb2-642737df2048");

// Получаем ссылку напрямую через менеджер справочника
Ссылка = Справочники[ИмяСправочника].ПолучитьСсылку(НовыйGUID);

Этот способ безупречно работает и очень прост в понимании, но имеет существенный недостаток: он не универсален. Если на вход вашей функции может прийти не только справочник, но и документ, план видов характеристик или задача, то такой жестко прописанный код вызовет ошибку выполнения.


Способ 2. Использование функций Библиотеки Стандартных Подсистем (БСП)

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

Рассмотрим, как с помощью БСП получить менеджер объекта по его полному имени (например, "Справочник.Номенклатура" или "Документ.РеализацияТоваровУслуг"), а затем извлечь ссылку:


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

// Используем функцию общего назначения БСП для получения менеджера
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ПолноеИмяМетаданных);

// Получаем ссылку по Уникальному Идентификатору
Ссылка = МенеджерОбъекта.ПолучитьСсылку(УникальныйИдентификатор);

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


// Пример упрощенной логики парсинга, если БСП недоступна в вашей конфигурации:
МассивИмен = СтрРазделить(ПолноеИмяМетаданных, ".");
КлассМетаданных = МассивИмен[0];
ИмяОбъекта = МассивИмен[1];

Если КлассМетаданных = "Справочник" Тогда
    Менеджер = Справочники[ИмяОбъекта];
ИначеЕсли КлассМетаданных = "Документ" Тогда
    Менеджер = Документы[ИмяОбъекта];
// И так далее для всех ссылочных типов...
КонецЕсли;

Ссылка = Менеджер.ПолучитьСсылку(УникальныйИдентификатор);

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


Способ 3. Создание ссылки через конструктор «Новый» по типу данных

Более изящный способ, заложенный в саму платформу 1С:Предприятие 8, — использование конструктора Новый(). Этот конструктор умеет создавать ссылку, если ему передать объект Тип и сам УникальныйИдентификатор:

Ссылка = Новый(ТипСсылка, УникальныйИдентификатор);

Главный вопрос здесь: как быстро и без лишних затрат получить тип ссылки, имея лишь объект метаданных? Если у нас есть объект метаданных, мы можем обратиться к встроенным механизмам платформы, однако прямого свойства "Тип" у объекта метаданных нет. Нам нужно получить пустую ссылку этого объекта и взять её тип.

Выясним, как это сделать оптимально в следующем разделе.


Способ 4. Универсальный способ через «ПредопределенноеЗначение» (без парсинга и БСП)

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

Разберем готовое решение по шагам:


// 1. Формируем путь для получения пустой ссылки
ПутьКПустойСсылке = ОбъектМетаданных.ПолноеИмя() + ".ПустаяСсылка";

// 2. Получаем саму пустую ссылку с помощью системной функции
ПустаяСсылка = ПредопределенноеЗначение(ПутьКПустойСсылке);

// 3. Извлекаем тип нашей пустой ссылки
ТипСсылки = ТипЗнч(ПустаяСсылка);

// 4. Создаем готовую заполненную ссылку с нужным GUID
Ссылка = Новый(ТипСсылки, УникальныйИдентификатор);

Преимущества данного подхода:

  1. Полная универсальность. Код работает абсолютно одинаково для справочников, документов, планов счетов, планов видов характеристик, задач и бизнес-процессов.
  2. Отсутствие парсинга. Нам больше не нужно делить строки по точкам, анализировать классы метаданных и писать условия.
  3. Работа на клиенте и сервере. Системная функция ПредопределенноеЗначение() доступна в любом контексте выполнения, включая тонкий клиент.
  4. Чистота кода. Решение занимает всего несколько строк без привлечения модулей БСП.

Способ 5. Высокопроизводительный метод через XML-сериализацию

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

Для оптимизации скорости выполнения операций мы рекомендуем использовать встроенный механизм XML-сериализации. Платформенная функция XMLЗначение() работает чрезвычайно быстро, так как ее алгоритмы реализованы на низком уровне C++ ядра платформы.

Посмотрим на пример реализации:


// 1. Получаем тип ссылки динамически (используя наш предыдущий прием)
ТипСсылки = ТипЗнч(ПредопределенноеЗначение(ОбъектМетаданных.ПолноеИмя() + ".ПустаяСсылка"));

// 2. Преобразуем наш уникальный идентификатор в строковый вид (с дефисами)
СтрокаGUID = Строка(УникальныйИдентификатор);

// 3. Мгновенно конструируем готовую ссылку через XML-сериализатор
Ссылка = XMLЗначение(ТипСсылки, СтрокаGUID);

Важная особенность: функция XMLЗначение() принимает на вход строковое представление GUID (например, "88d54406-36a1-11e9-8bb2-642737df2048"). Это значит, что если вы считываете GUID в виде текста из внешнего источника (XML, JSON, CSV), вам даже не потребуется предварительно создавать тяжелый объект УникальныйИдентификатор через Новый, что дает дополнительный прирост производительности!


Способ 6. Низкоуровневый хак через десериализацию внутренней строки

Этот метод относится к категории продвинутых приемов разработки ("хаков") и основан на особенностях работы внутренней системы типизации 1С. Внутренний формат хранения ссылок в 1С (получаемый через ЗначениеВСтрокуВнутр()) выглядит как строка специального вида, содержащая идентификатор класса объекта метаданных и сам GUID, записанный без дефисов.

Если мы заменим область уникального идентификатора в шаблоне пустой ссылки на наш GUID и выполним обратное преобразование, мы мгновенно получим готовую типизированную ссылку без обращений к базе данных.

Рассмотрим этот алгоритм детально:


// 1. Получаем внутреннее строковое представление пустой ссылки нужного типа
ШаблонВнутреннейСтроки = ЗначениеВСтрокуВнутр(ПредопределенноеЗначение(ОбъектМетаданных.ПолноеИмя() + ".ПустаяСсылка"));

// Пример получаемой строки: "{"#",b15f9393-5750-48af-83f1-73600f14d187,00000000000000000000000000000000}"
// Где "00000000000000000000000000000000" — это область под GUID пустой ссылки.

// 2. Приводим наш уникальный идентификатор к строке без дефисов
СтрокаУИДБезДефисов = СтрЗаменить(Строка(УникальныйИдентификатор), "-", "");

// 3. Подменяем нули в шаблоне внутренней строки на наш реальный GUID
ВнутренняяСтрока = СтрЗаменить(ШаблонВнутреннейСтроки, "00000000000000000000000000000000", СтрокаУИДБезДефисов);

// 4. Восстанавливаем ссылку из измененной внутренней строки
Ссылка = ЗначениеИзСтрокиВнутр(ВнутренняяСтрока);

Когда стоит применять этот метод? Он идеален, если вы парсите навигационные ссылки 1С (e1cib-ссылки), в которых уникальный идентификатор уже представлен в виде сплошной строки без дефисов. В таком случае производительность механизма будет максимальной, так как отсутствуют лишние операции по форматированию строк.

Важное предупреждение: методы ЗначениеВСтрокуВнутр() и ЗначениеИзСтрокиВнутр() не рекомендуется использовать в кодовой базе, предназначенной для тиражируемых решений, поскольку структура внутренней строки платформы является закрытой информацией и теоретически может измениться в будущих мажорных релизах платформы (хотя она остается неизменной уже многие годы).


Сравнительный анализ решений

Чтобы вам было проще выбрать подходящий инструмент для решения конкретной прикладной задачи, сопоставим рассмотренные методы по ключевым критериям:

Используя приведенные примеры и выбрав наиболее подходящий под ваши требования метод, вы сможете писать производительный, читаемый и надежный код при работе с динамическими ссылками в 1С:Предприятии 8.

← На главную