В процессе разработки универсальных механизмов или инструментов для анализа конфигурации программисты 1С часто сталкиваются с необходимостью динамического получения типов. Одной из самых коварных задач является работа с коллекцией ПеречислимыеСвойстваОбъектовМетаданных. К этой коллекции относятся такие системные свойства, как РежимСовместимости, ВариантВстроенногоЯзыка, ОбновлениеПредопределенныхДанных и многие другие.
Разберем ситуацию: вам нужно получить объект Тип для значения РежимСовместимости, зная только строковое имя этого свойства. Стандартный подход с использованием функции Тип("СтроковоеИмя") здесь не сработает. Проанализируем причины этого поведения и рассмотрим правильные способы решения задачи.
Рассмотрим стандартное поведение платформы. Мы привыкли, что для системных перечислений, таких как ТипУзлаXML или ВидДвиженияНакопления, мы можем легко получить тип из строки:
ТипЗначения = Тип("ТипУзлаXML"); // Вернет тип системного перечисления
Однако в случае со свойствами объектов метаданных (коллекция Метаданные.СвойстваОбъектов), ситуация иная. Тип ПеречислимыеСвойстваОбъектовМетаданных.РежимСовместимости является внутренним типом платформы, предназначенным для описания самой структуры метаданных. Платформа не регистрирует строковые литералы для этих типов в глобальном пространстве имен. Попытка вызвать Тип("ПеречислимыеСвойстваОбъектовМетаданных.РежимСовместимости") всегда будет возвращать Неопределено.
Выясним самый простой и надежный способ. Если нам известен путь к свойству в дереве метаданных, мы можем получить тип, обратившись к любому из существующих значений этого свойства. Посмотрим на пример кода:
// Получаем тип напрямую от одного из значений перечисления
НужныйТип = ТипЗнч(Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать);
Этот метод работает безотказно, так как функция ТипЗнч() анализирует реальный объект в памяти, а не пытается сопоставить строку с таблицей типов. Однако этот способ не является универсальным, так как требует жесткого написания имени свойства в коде.
Если перед нами стоит задача написать универсальную функцию, которая принимает имя свойства (например, "РежимСовместимости") и возвращает тип его значений, нам придется использовать коллекцию Метаданные.СвойстваОбъектов. Разберем алгоритм решения по шагам:
Метаданные.СвойстваОбъектов по строковому имени.Проанализируем пример кода для реализации этой логики:
Функция ПолучитьТипСвойстваМетаданных(ИмяСвойства) Экспорт
// ИмяСвойства = "РежимСовместимости"
СвойствоМетаданных = Метаданные.СвойстваОбъектов[ИмяСвойства];
// Для системных перечислений метаданных мы можем перебрать их значения
// или обратиться к первому попавшемуся.
// В данном случае, обращение через точку к конкретному имени
// (например, "НеИспользовать") — самый быстрый путь,
// если мы знаем структуру этого конкретного свойства.
Если ИмяСвойства = "РежимСовместимости" Тогда
Возврат ТипЗнч(Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать);
КонецЕсли;
Возврат Неопределено;
КонецФункции
Рассмотрим ситуацию, когда нам нужно проверить, относится ли значение к конкретному типу свойств метаданных. Мы можем заранее сформировать объект ОписаниеТипов, используя массив из типов, полученных через ТипЗнч(). Это полезно при массовых проверках в циклах. Посмотрим на пример:
МассивТипов = Новый Массив;
МассивТипов.Добавить(ТипЗнч(Метаданные.СвойстваОбъектов.РежимСовместимости.Версия8_1));
// Описание типов теперь содержит нужный нам "скрытый" тип
НужноеОписаниеТипов = Новый ОписаниеТипов(МассивТипов);
// Теперь мы можем проверять любые значения
Если НужноеОписаниеТипов.СодержитТип(ТипЗнч(Метаданные.РежимСовместимости)) Тогда
Сообщить("Типы совпадают!");
КонецЕсли;
Важно помнить, что все значения одного системного перечисления имеют один и тот же тип. Поэтому в массив достаточно добавить лишь одно любое значение (например, Версия8_1 или НеИспользовать), чтобы ОписаниеТипов корректно распознавало все остальные значения этого же перечисления.
Проанализируем важный нюанс: коллекция СвойстваОбъектов содержит объекты, которые описывают возможные значения настроек самой платформы. Когда мы пишем Метаданные.РежимСовместимости, мы получаем текущее значение этой настройки для данной конфигурации. Тип этого значения и будет тем самым искомым ПеречислимыеСвойстваОбъектовМетаданных.РежимСовместимости.
Если ваша задача — получить тип максимально универсально, можно использовать следующий "трюк" с метаданными:
// Динамическое получение значения через квадратные скобки
ИмяСвойство = "РежимСовместимости";
ЗначениеСвойства = Метаданные[ИмяСвойство];
ТипСвойства = ТипЗнч(ЗначениеСвойства);
Этот код сработает, так как Метаданные[ИмяСвойство] вернет текущую установку конфигурации, а ТипЗнч() определит её тип. Это избавляет от необходимости знать конкретные имена элементов перечисления (таких как Версия8_3_12).
Подведем итоги нашего исследования. Мы выяснили, что:
Тип() не поддерживает строковые литералы для коллекции ПеречислимыеСвойстваОбъектовМетаданных.Тип — использовать ТипЗнч().Метаданные[ИмяСвойства].Новый, их можно только считывать из свойств метаданных.Используя предложенные методы, вы сможете корректно обрабатывать типы системных настроек в своих универсальных обработках и инструментах анализа метаданных.