Работа с 1С через COMConnector из среды .NET (C#) часто сопряжена с трудностями интерпретации типов данных. В отличие от нативного языка 1С, где метаданные доступны напрямую, в C# мы получаем объекты __ComObject или dynamic, свойства которых не всегда очевидны. Разберем подробно, как определить, какой тип данных скрывается за реквизитом, и как отличить простую строку от ссылки на справочник.
Прежде всего, проанализируем, что возвращает реквизит метаданных. В 1С свойство Тип у объекта метаданных реквизита возвращает объект ОписаниеТипов (TypeDescription). Важно помнить, что 1С поддерживает составные типы, поэтому ОписаниеТипов — это всегда коллекция, даже если выбран только один тип.
Рассмотрим базовый алгоритм получения типов на стороне C#:
// Предположим, 'connection' — это ваше COM-соединение (V83.COMConnector)
// 'propertyMetadata' — объект метаданных конкретного реквизита
dynamic typeDescription = propertyMetadata.Type; // ОписаниеТипов
dynamic typesArray = typeDescription.Types(); // Вызов метода Типы()
int count = typesArray.Count(); // Количество типов в составе
for (int i = 0; i < count; i++)
{
dynamic currentType = typesArray.Get(i); // Получаем конкретный объект Тип
// Дальнейшая логика анализа
}
Одним из самых простых и эффективных способов узнать строковое наименование типа в формате XML является использование методов глобального контекста 1С через объект соединения. Рассмотрим использование XMLString и XMLTypeOf. Эти методы позволяют получить строковый идентификатор, который легко обработать в C#.
Проанализируем пример кода, который поможет получить имя типа:
// Получаем строковое представление типа
string xmlTypeName = connection.XMLString(currentType);
// Для простых типов это вернет что-то вроде "string", "decimal"
// Для ссылок — описание типа в формате XML
Однако стоит быть осторожными: вызов XMLString напрямую к объекту ОписаниеТипов может привести к ошибке. Всегда извлекайте конкретный Тип из коллекции Types(), как показано выше.
Если нам нужно выяснить, является ли тип ссылочным (например, СправочникСсылка или ДокументСсылка), и получить доступ к его метаданным, лучше всего использовать метод FindByType объекта Metadata. Это наиболее профессиональный подход.
Разберем этот процесс по шагам:
Тип из ОписаниеТипов.connection.Metadata.FindByType().null, перед нами ссылочный тип, и мы можем прочитать его полное имя.Посмотрим на программную реализацию:
dynamic foundMetadata = connection.Metadata.FindByType(currentType);
if (foundMetadata != null)
{
string fullName = foundMetadata.FullName(); // Например, "Справочник.Номенклатура"
string synonym = foundMetadata.Synonym;
Console.WriteLine($"Это ссылка: {fullName} ({synonym})");
}
else
{
Console.WriteLine("Это простой тип (строка, число, дата или булево)");
}
Иногда полезно получить информацию о типе уже имеющегося значения (объекта), а не просто описание из метаданных. В 1С для этого служит функция ТипЗнч. При работе через COM её необходимо вызывать у объекта соединения.
Выясним причину, почему прямой вызов может не работать: в C# необходимо следить за языком интерфейса. Если COM-соединение инициализировано с поддержкой английского, лучше использовать TypeValue. Однако самым надежным способом будет использование функции String() для получения человекочитаемого названия типа.
// Получаем значение реквизита
dynamic value = objectRef.Description;
// Получаем тип значения
dynamic typeOfValue = connection.TypeValue(value);
// Преобразуем тип в строку для анализа
string typeString = connection.String(typeOfValue);
// Вернет "Строка" или "Справочник ссылка: Номенклатура"
Используйте англоязычные аналоги методов. Рассмотрим ситуацию: при вызове .Типы() в некоторых версиях C# и настройках локали могут возникать ошибки. Использование .Types(), .Count(), .Get() вместо .Получить() делает код более стабильным при работе через COM-интерфейс.
Обработка Null и Неопределено. В 1С существуют специфические значения Null и Неопределено. В C# они могут приходить как DBNull.Value или специфические COM-объекты. Перед анализом типа всегда проверяйте значение:
if (value == null || value is DBNull)
{
// Обработка пустого значения
}
Выполнение кода на стороне 1С. Если логика определения типа становится слишком сложной для реализации на C#, мы можем воспользоваться методами Вычислить() (Eval) или Выполнить() (Execute) самого соединения. Это позволит перенести часть логики непосредственно в среду 1С, вернув в C# уже готовый результат (например, строку или булево значение).
// Пример использования Eval для проверки на тип
bool isNomenclature = connection.Eval($"ТипЗнч(Объект) = Тип(\"СправочникСсылка.Номенклатура\")");
Подводя итог, можно сказать, что работа с типами через COM требует понимания того, что почти любая операция должна проходить через объект connection. Не пытайтесь обращаться к методам типа напрямую в C#, так как они не являются частью интерфейса IDispatch объекта типа, а являются функциями глобального контекста 1С.