При работе с механизмом XDTO (XML Data Transfer Objects) программисты часто сталкиваются с задачей программного формирования объектов, которые должны быть десериализованы в стандартные типы 1С, такие как НаборЗаписейМенеджер. Одной из наиболее острых проблем является заполнение свойств с универсальным типом anyType или anySimpleType. Типичный пример — поле Value в структуре FilterItem, которое используется для установки отбора в наборе записей (например, по регистратору).
В этой статье мы подробно разберем, почему возникает ошибка «Отображение типа в anySimpleType», и рассмотрим правильные способы программного заполнения таких полей, чтобы метод ПрочитатьXDTO корректно создавал объект в базе данных.
Рассмотрим ситуацию: нам необходимо создать объект AccumulationRegisterRecordSet через фабрику XDTO. Мы успешно создаем записи (строки), но при попытке установить фильтр по регистратору через объект Filter возникает ошибка. Проблема кроется в строке кода, где свойству Value напрямую присваивается ссылка 1С:
ЗаписьФильтра_Объект.Value = Документы.ПоступлениеТоваров.ПолучитьСсылку(Новый УникальныйИдентификатор(Идентификатор));
Ошибка «Отображение типа DocumentRef.ПоступлениеТоваров в тип anySimpleType» возникает из-за того, что механизм XDTO не знает, как автоматически преобразовать сложный объект ссылки 1С в неопределенный тип anyType. Поскольку anyType может содержать практически любую структуру, фабрике XDTO требуется явное указание типа (аннотация xsi:type), чтобы при последующем чтении система понимала, что перед ней именно ссылка на конкретный документ, а не просто строковый GUID.
Самый надежный способ решить проблему — это создать промежуточный объект ОбъектXDTO, который будет жестко типизирован согласно схеме метаданных вашей конфигурации. Проанализируем шаги, необходимые для реализации этого подхода:
Тип фабрики, указывая пространство имен текущей конфигурации. Для ссылок это обычно http://v8.1c.ru/8.1/data/enterprise/current-config, а имя типа строится как DocumentRef.ИмяДокумента или CatalogRef.ИмяСправочника.Создать генерируем объект, передавая туда тип и саму ссылку.anyType.Посмотрим на практический пример кода:
// 1. Получаем ссылку
СсылкаНаДокумент = Документы.ПоступлениеТоваров.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаИдентификатор));
// 2. Находим нужный тип в фабрике XDTO
ТипСсылкаXDTO = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "DocumentRef.ПоступлениеТоваров");
// 3. Создаем типизированное значение XDTO
СсылкаXDTO = ФабрикаXDTO.Создать(ТипСсылкаXDTO, СсылкаНаДокумент);
// 4. Устанавливаем значение в фильтр
ЗаписьФильтра_Объект.Value = СсылкаXDTO;
В этом случае в итоговом XML-файле или объекте появится атрибут xsi:type, который позволит методу СериализаторXDTO.ПрочитатьXDTO() безошибочно восстановить ссылку при записи набора.
Если в вашем коде типы документов могут меняться или вы хотите написать более универсальную обработку, использование жестких строк вида "DocumentRef.ПоступлениеТоваров" не всегда удобно. Проанализируем более гибкий метод с использованием встроенного сериализатора.
Метод СериализаторXDTO.ЗаписатьXDTO(Значение) возвращает готовый ОбъектXDTO. Он автоматически определяет тип переданного объекта и подбирает соответствующее описание из фабрики. Это идеальное решение для заполнения полей anyType.
Разберем пример реализации:
// Вместо ручного поиска типа используем возможности сериализатора
Ссылка = Документы.ПоступлениеТоваров.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаИдентификатор));
ЗаписьФильтра_Объект.Value = СериализаторXDTO.ЗаписатьXDTO(Ссылка);
Этот подход короче, безопаснее и автоматически поддерживает любые типы ссылок (справочники, документы, бизнес-процессы), не требуя ручного формирования имен типов.
Чтобы картина была полной, рассмотрим, как собрать весь объект набора записей регистра накопления целиком. Выясним, какие свойства являются ключевыми для того, чтобы 1С восприняла сформированный XDTO-объект как валидный набор записей.
// Определяем типы для набора записей
ТипНабора = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "AccumulationRegisterRecordSet.ТоварыОрганизаций");
Набор_Объект = ФабрикаXDTO.Создать(ТипНабора);
// Заполнение самих записей (движений)
ТипЗаписи = ТипНабора.Свойства.Получить("Record").Тип;
Для Каждого ДанныеИзИсточника Из МассивДанных Цикл
НоваяЗапись = ФабрикаXDTO.Создать(ТипЗаписи);
НоваяЗапись.Period = ДанныеИзИсточника.Период;
НоваяЗапись.Recorder = СсылкаРегистратор; // Здесь тоже может потребоваться ЗаписатьXDTO, если тип anyType
НоваяЗапись.Active = Истина;
// ... заполнение измерений и ресурсов
Набор_Объект.Record.Добавить(НоваяЗапись);
КонецЦикла;
// Формирование обязательного фильтра (без него набор не запишется корректно)
ТипФильтра = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise", "Filter");
ОбъектФильтра = ФабрикаXDTO.Создать(ТипФильтра);
ТипЭлементаФильтра = ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise", "FilterItem");
ЭлементФильтра = ФабрикаXDTO.Создать(ТипЭлементаФильтра);
ЭлементФильтра.Name = "Recorder";
ЭлементФильтра.Value = СериализаторXDTO.ЗаписатьXDTO(СсылкаРегистратор);
ОбъектФильтра.FilterItem.Добавить(ЭлементФильтра);
Набор_Объект.Filter = ОбъектФильтра;
// Десериализация в объект 1С и запись
ЗаписываемыйОбъект = СериализаторXDTO.ПрочитатьXDTO(Набор_Объект);
ЗаписываемыйОбъект.ОбменДанными.Загрузка = Истина;
ЗаписываемыйОбъект.Записать();
При использовании данных методов стоит учитывать несколько технических нюансов, которые помогут избежать ошибок в промышленной эксплуатации:
Recorder (Регистратор) в каждой записи коллекции Record должно строго совпадать со значением, указанным в Filter. Если они будут отличаться, метод Записать() может выдать ошибку или привести к непредсказуемому поведению в базе данных.Загрузка = Истина. Это отключает проверки в модулях набора записей и позволяет избежать конфликтов бизнес-логики.ФабрикаXDTO.Создать может работать медленнее, чем прямая работа с объектом НаборЗаписейМенеджер. В таких случаях рассмотрите возможность формирования набора напрямую в 1С, если данные уже загружены во временную таблицу.http://v8.1c.ru/8.1/data/enterprise, а типы конкретной конфигурации (RecordSet, Record) — в http://v8.1c.ru/8.1/data/enterprise/current-config.Таким образом, мы выяснили, что ключ к успеху при работе с anyType в XDTO — это предоставление системе информации о типе данных. Используя явное создание объекта через ФабрикаXDTO.Создать или универсальный метод СериализаторXDTO.ЗаписатьXDTO, вы сможете корректно передавать ссылки и другие сложные типы данных, обеспечивая надежный обмен данными между системами.