При эксплуатации программных продуктов на базе 1С:Предприятие 8.3, в частности конфигурации 1С:Розница, специалисты часто сталкиваются с ситуацией, когда после планового обновления конфигурации или платформы перестает работать привычный обмен данными с интернет-магазином. Одной из наиболее распространенных и неприятных ошибок является сообщение: Метод объекта не обнаружен (Свойство). Чаще всего это происходит в процедурах обработки адресных сведений или контактной информации. В данной статье мы подробно разберем, почему возникает эта проблема, проанализируем механизмы работы с объектами XDTO и предложим несколько вариантов решения задачи.
Для начала проанализируем ситуацию, в которой возникает сбой. Ошибка локализуется в коде, который отвечает за формирование представления адреса. Рассмотрим типичный фрагмент кода, который вызывает исключение:
Если НЕ ОбъектАдреса.Свойство("AddressType") Тогда
СписокПолейАдреса = "Area,City";
ИначеЕсли РаботаСАдресамиКлиентСервер.ЭтоМуниципальныйАдрес(ОбъектАдреса.AddressType) Тогда
СписокПолейАдреса = "Area,MunDistrict,Settlement,CityDistrict,Locality,Territory";
Иначе
СписокПолейАдреса = "Area,District,City,CityDistrict,Locality,Territory";
КонецЕсли;
Проблема заключается в том, что переменная ОбъектАдреса имеет тип ОбъектXDTO. В языке программирования 1С метод Свойство() является стандартным методом для объекта типа Структура или Соответствие. Однако у ОбъектаXDTO такого метода не существует — вместо него используется коллекция Свойства() или прямое обращение к метаданным пакета XDTO.
Почему раньше все работало? Разберем этот момент. Скорее всего, до обновления конфигурация использовала упрощенные структуры для передачи данных адреса. После перехода на новые версии Библиотеки стандартных подсистем (БСП) и внедрения поддержки классификатора ГАР (ФИАС), механизмы работы с адресами были переведены на использование XML-схем и объектов XDTO. Старый код обмена, не рассчитанный на такие изменения, продолжает обращаться к объекту как к структуре, что и приводит к фатальной ошибке.
Если нам необходимо быстро восстановить работоспособность обмена, не переписывая логику взаимодействия с XDTO-пакетами, можно создать вспомогательную функцию, которая будет эмулировать проверку наличия свойства. Рассмотрим пример такой функции, которая использует особенность метода ЗаполнитьЗначенияСвойств():
&НаСервере
Функция ПеременнаяСодержитСвойство(Переменная, ИмяСвойства) Экспорт
// Инициализируем структуру для теста с ключом и значением NULL
СтруктураПроверка = Новый Структура;
СтруктураПроверка.Вставить(ИмяСвойства, NULL);
// Пытаемся заполнить структуру из переданного объекта (даже если это ОбъектXDTO)
ЗаполнитьЗначенияСвойств(СтруктураПроверка, Переменная);
// Если значение для свойства осталось NULL, значит свойство в объекте не найдено
Если СтруктураПроверка[ИмяСвойства] = NULL Тогда
Возврат Ложь;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции
В основном коде вместо прямого вызова метода Свойство() мы будем использовать нашу новую функцию:
Если НЕ ПеременнаяСодержитСвойство(ОбъектАдреса, "AddressType") Тогда
// логика обработки
КонецЕсли;
Важный нюанс: Этот метод является «обходным маневром». Он позволяет избежать ошибки «Метод не обнаружен», но может повлечь за собой другие сложности, если объект XDTO содержит вложенные структуры, которые метод ЗаполнитьЗначенияСвойств не сможет обработать корректно.
Более надежным и «чистым» способом с точки зрения архитектуры 1С является предварительное преобразование объекта XDTO в привычную структуру. В современных редакциях 1С:Розница и других решениях на базе БСП для этого существуют стандартные средства. Рассмотрим, как это сделать:
Мы можем воспользоваться методом общего модуля ОбщегоНазначения.XDTOОбъектВСтруктуру(ОбъектXDTO). Проанализируем, как изменится наш код:
// Преобразуем XDTO в структуру перед обработкой
ДанныеАдреса = ОбщегоНазначения.XDTOОбъектВСтруктуру(ОбъектАдреса);
Если НЕ ДанныеАдреса.Свойство("AddressType") Тогда
СписокПолейАдреса = "Area,City";
// Далее работаем с переменной ДанныеАдреса как с обычной структурой
Этот подход предпочтительнее, так как он полностью снимает вопросы типизации и позволяет использовать весь стандартный функционал работы со структурами, включая метод Свойство().
Если мы хотим работать напрямую с объектом XDTO (например, для сохранения высокой производительности при больших объемах данных), нам следует использовать проверку наличия свойства через метаданные самого объекта. Посмотрим на пример реализации такой проверки:
Если ОбъектАдреса.Свойства().Получить("AddressType") = Неопределено Тогда
// Свойство не описано в схеме XDTO для данного объекта
Иначе
// Свойство существует, можем обращаться
ЗначениеТипа = ОбъектАдреса.AddressType;
КонецЕсли;
Этот метод является наиболее корректным при работе с XML и XDTO, так как он не создает лишних копий данных в памяти, в отличие от преобразования в структуру.
Как отметил автор темы, после исправления первой ошибки часто возникает вторая: Метод объекта не обнаружен при вызове других функций, например, РаботаСАдресамиКлиентСервер.ЭтоМуниципальныйАдрес. Это происходит потому, что при обновлении конфигурации разработчики 1С часто проводят рефакторинг общих модулей.
Проанализируем шаги для решения этой проблемы:
Ctrl+Shift+F для поиска имени пропавшей функции по всей конфигурации. Велика вероятность, что она была перемещена в другой модуль (например, из РаботаСАдресамиКлиентСервер в РаботаСАдресами или в служебные модули типа КонтактнаяИнформацияСлужебный).Чтобы точно определить, какой тип данных приходит в функцию в момент ошибки, рекомендуем использовать Отладчик. Выполните следующие действия:
ТипЗнч(ОбъектАдреса).ОбъектXDTO, значит, использование .Свойство() недопустимо.ОбъектАдреса.Свойства(), чтобы увидеть список доступных полей, приходящих с сайта.Подводя итог, можно сказать, что проблема «Метод объекта не обнаружен (Свойство)» в 1С:Розница — это типичный симптом «устаревания» кода обмена относительно ядра конфигурации. Применяя системный подход и используя стандартные функции БСП, вы сможете не только устранить ошибку, но и сделать ваш код более устойчивым к будущим обновлениям программы.