Как программно проверить, является ли тип значения переменной «СправочникМенеджер»

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

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

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

Самый простой и очевидный способ, который часто первым приходит в голову, — это анализ строкового представления типа переменной. Разберем его реализацию:


Если Лев(СокрЛП(ТипЗнч(Переменная)), 19) = "Справочник менеджер" Тогда
    // Это менеджер справочника
КонецЕсли;

Рассмотрим нюансы этого метода. Основной недостаток заключается в его зависимости от локализации (языка) интерфейса платформы. Если код будет выполняться в системе с английской локалью, ТипЗнч вернет "CatalogManager", и условие не сработает. Также этот метод считается «некрасивым» с точки зрения стандартов разработки 1С, так как строковые операции медленнее прямых сравнений типов.

Способ 2. Использование метаданных и коллекции Справочники

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


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

ЭтоМенеджер = мдОбъекта <> Неопределено 
              И Метаданные.Справочники.Содержит(мдОбъекта) 
              И МояПеременная = Справочники[мдОбъекта.Имя];

Выясним причину, почему это работает. Функция НайтиПоТипу возвращает объект метаданных (например, ОбъектМетаданных: Справочник.Номенклатура) одинаково для ссылки, объекта и менеджера этого справочника. Однако ключевой момент здесь — сравнение МояПеременная = Справочники[Имя]. Только менеджер справочника будет равен элементу глобальной коллекции Справочники. Ссылка или объект это сравнение не пройдут.

Способ 3. Использование XML-типа (независимость от локали)

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


ТипXML = XMLТипЗнч(МояПеременная);
Если ТипXML <> Неопределено И Найти(ТипXML.ИмяТипа, "CatalogManager") > 0 Тогда
    Сообщить("Это менеджер справочника!");
КонецЕсли;

Посмотрим на результат: имя типа в формате XML для любого менеджера справочника всегда будет содержать подстроку CatalogManager, независимо от того, какой язык установлен в системе.

Способ 4. Создание кэша менеджеров (оптимизация производительности)

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

Рассмотрим пример кода для инициализации такого кэша:


// В модуле управляемого приложения или глобальном модуле
Перем КэшМенеджеров Экспорт;

Процедура ИнициализироватьКэш()
    КэшМенеджеров = Новый Соответствие;
    Для Каждого МдСпр Из Метаданные.Справочники Цикл
        Менеджер = Справочники[МдСпр.Имя];
        КэшМенеджеров.Вставить(ТипЗнч(Менеджер), Истина);
    КонецЦикла;
КонецПроцедуры

// Использование в коде
Если КэшМенеджеров.Получить(ТипЗнч(ПроверяемаяПеременная)) = Истина Тогда
    // Это менеджер
КонецЕсли;

Этот способ является самым быстрым, так как поиск в Соответствие по типу происходит практически мгновенно.

Способ 5. Проверка через ОписаниеТипов

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


МассивТиповМенеджеров = Новый Массив;
Для Каждого Спр Из Метаданные.Справочники Цикл
    МассивТиповМенеджеров.Добавить(ТипЗнч(Справочники[Спр.Имя]));
КонецЦикла;

Описатель = Новый ОписаниеТипов(МассивТиповМенеджеров);

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

Способ 6. Использование метода ТипМенеджера (для платформы 8.3)

В современных версиях платформы 1С:Предприятие 8.3 можно получить тип менеджера напрямую, не прибегая к хитростям с коллекциями. Рассмотрим этот подход:


мдОбъекта = Метаданные.НайтиПоТипу(ТипЗнч(Переменная));
Если мдОбъекта <> Неопределено Тогда
    ИмяСправочника = мдОбъекта.Имя;
    Если ТипЗнч(Переменная) = Справочники.ТипМенеджера(ИмяСправочника) Тогда
        // Это точно менеджер
    КонецЕсли;
КонецЕсли;

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

Подведение итогов

Мы рассмотрели несколько вариантов решения задачи. Выбор конкретного метода зависит от ваших целей:

  1. Для быстрых разовых проверок подойдет метод со сравнением МояПеременная = Справочники[мд.Имя].
  2. Для универсальных механизмов, работающих в разных странах, лучше использовать XMLТипЗнч.
  3. Для оптимизации скорости в циклах или часто вызываемых процедурах рекомендуется использовать предварительно заполненное Соответствие или ОписаниеТипов.

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

← На главную