В процессе разработки на платформе 1С:Предприятие 8 программисты часто сталкиваются с необходимостью динамически определять, к какому классу относится тот или иной объект. Это особенно актуально при работе с реквизитами составного типа, универсальными обработками или когда требуется анализ зависимостей конфигурации. Рассмотрим подробнее все существующие способы решения этой задачи, проанализируем их производительность и выберем наиболее оптимальные подходы.
Самый простой и быстрый способ узнать тип конкретной ссылки — использовать встроенную функцию ТипЗнч. Этот метод работает на уровне идентификаторов типов в оперативной памяти, что делает его крайне производительным. Разберем пример, когда нам нужно проверить, является ли переменная ссылкой на конкретный справочник.
Если ТипЗнч(ВыбранныйОбъект) = Тип("СправочникСсылка.Номенклатура") Тогда
// Выполняем действия, специфичные для номенклатуры
Сообщить("Это номенклатура");
КонецЕсли;
Важно помнить, что функция Тип принимает строковое имя типа. Для ссылочных объектов формат всегда будет КлассОбъектаСсылка.ИмяОбъекта. Если мы работаем с документами, условие будет выглядеть как Тип("ДокументСсылка.РеализацияТоваровУслуг"). Для быстрой проверки таких конструкций удобно использовать консоль кода с ИИ-помощником.
Часто возникает вопрос: как определить, является ли объект документом или справочником вообще, не привязываясь к конкретному виду (например, любая накладная или любой элемент справочника)? Для этого в глобальном контексте существуют коллекции Справочники, Документы, ПланыВидовХарактеристик и другие, у которых есть свойство ТипВсеСсылки.
Проанализируем пример кода для такой проверки:
ТипОбъекта = ТипЗнч(ВыбранныйОбъект);
Если Справочники.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
Сообщить("Переданное значение — это ссылка на какой-то справочник");
ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
Сообщить("Переданное значение — это ссылка на какой-то документ");
КонецЕсли;
Этот метод считается "каноническим" для платформы 8.3. Он надежен и позволяет быстро классифицировать объект. Однако стоит учитывать, что если ВыбранныйОбъект равен Неопределено, проверка может вернуть ложный результат. Для выбора конкретных типов в интерфейсе может пригодиться универсальная форма выбора типа.
Иногда нам нужно получить более детальную информацию или просто строковое представление класса объекта. Мы можем обратиться к свойству Метаданные самого объекта или использовать информер по метаданным. Рассмотрим ситуацию, когда у нас есть только тип значения, и мы хотим понять, к какой коллекции он относится.
ТекущийТип = ТипЗнч(ОбъектСсылка);
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТекущийТип);
Если ОбъектМетаданных = Неопределено Тогда
Возврат; // Тип не найден в метаданных (например, число или строка)
КонецЕсли;
Если Метаданные.Справочники.Содержит(ОбъектМетаданных) Тогда
Сообщить("Это справочник: " + ОбъектМетаданных.Имя);
ИначеЕсли Метаданные.Документы.Содержит(ОбъектМетаданных) Тогда
Сообщить("Это документ: " + ОбъектМетаданных.Имя);
КонецЕсли;
Важное замечание по производительности: Обращение к ОбъектСсылка.Метаданные() является достаточно "дорогой" операцией, так как заставляет платформу обращаться к структуре конфигурации. Если вам нужно просто сравнить типы в цикле, всегда отдавайте предпочтение ТипЗнч.
Если вам нужно получить строковое представление типа для логирования или динамического формирования запросов, удобно использовать свойство ПолноеИмя. Оно возвращает строку вида Справочник.Валюты или Документ.ПоступлениеТоваровУслуг.
Посмотрим, как можно реализовать проверку через анализ строки:
ПолноеИмя = ОбъектСсылка.Метаданные().ПолноеИмя();
// Проверяем первые символы строки
Если СтрНачинаетсяС(ПолноеИмя, "Справочник") Тогда
Сообщить("Объект относится к справочникам");
ИначеЕсли СтрНачинаетсяС(ПолноеИмя, "Документ") Тогда
Сообщить("Объект относится к документам");
КонецЕсли;
В старых версиях платформы (до появления СтрНачинаетсяС) программисты использовали функцию Лев(ПолноеИмя, 5), но современный подход делает код более читаемым и защищенным от ошибок. Также можно использовать СтрРазделить(ПолноеИмя, ".")[0], чтобы получить только имя базового класса (Справочник, Документ, РегистрСведений).
Если ваша конфигурация построена на базе БСП (как большинство современных типовых решений: УТ 11, ERP, БП 3.0), задачу определения типа можно решить одной строкой, используя общий модуль ОбщегоНазначения.
Разберем основные функции:
ОбщегоНазначения.ЭтоСсылка(ТипЗнч(Значение)) — возвращает Истина, если переданный тип является ссылочным.ОбщегоНазначения.ИмяБазовогоТипаПоОбъектуМетаданных(Значение.Метаданные()) — вернет строковое значение, например, "Справочники".Использование функций БСП гарантирует, что ваш код будет соответствовать стандартам разработки фирмы "1С" и корректно отработает во всех типовых сценариях.
Существует "хитрый" и очень быстрый способ получить информацию о типе без обращения к тяжелым объектам метаданных — использование функции XMLТип. Это полезно для высоконагруженных участков кода.
ДанныеТипа = XMLТип(ТипЗнч(ОбъектСсылка));
// ДанныеТипа.ИмяТипа вернет "CatalogRef.Номенклатура"
// ДанныеТипа.URIПространстваИмена вернет схему данных
Этот метод удобен тем, что возвращает фиксированную структуру, из которой легко извлечь англоязычное имя базового класса (например, CatalogRef, DocumentRef).
Иногда эффективнее определить тип объекта еще на этапе получения данных из базы, не выгружая сами объекты в память сервера приложений. В языке запросов 1С для этого предусмотрены специальные операторы.
Проанализируем пример запроса:
ВЫБРАТЬ
ВЫБОР
КОГДА Ссылка ССЫЛКА Справочник.Номенклатура ТОГДА "Это товар"
КОГДА Ссылка ССЫЛКА Справочник.Услуги ТОГДА "Это услуга"
ИНАЧЕ "Прочее"
КОНЕЦ КАК ВидОбъекта
ИЗ
Документ.РеализацияТоваровУслуг.Товары
Функция ТИПЗНАЧЕНИЯ(Поле) в запросе позволяет получить идентификатор типа, который можно сравнивать с эталонным с помощью оператора ТИП(Справочник.Склады). Это самый быстрый способ обработки больших массивов данных.
Подводя итог нашему разбору, можно выделить следующие правила выбора метода:
ТипЗнч(Объект) = Тип("..."). Это самый быстрый способ.Справочники.ТипВсеСсылки().СодержитТип().ОбщегоНазначения.ИмяБазовогоТипаПоОбъектуМетаданных() из БСП или парсинг ПолноеИмя()..Метаданные(), старайтесь работать с типами напрямую.Помните также о существовании других ссылочных типов, таких как Планы счетов, Задачи, Бизнес-процессы и Перечисления. Все описанные выше методы (кроме специфических для БСП) применимы и к ним.