При интеграции платформы 1С 7.7 с современными веб-сервисами и сторонними протоколами разработчики нередко обращаются к возможностям платформы .NET через универсальные COM-обертки, такие как NetObjectToIDispatch45. Однако при попытке вызвать методы внешних библиотек (например, сборки FluorineFx для протокола AMF3) часто возникают специфические ошибки поиска методов через механизм рефлексии или сложности с получением возвращаемых данных. Разберем по шагам, почему возникают подобные сбои и как правильно организовать взаимодействие с .NET-классами в 1С 7.7.
Рассмотрим типовой сценарий, в котором возникает ошибка. При попытке выполнить следующий код в среде 1С 7.7:
net = СоздатьОбъект("NetObjectToIDispatch45");
сборка = net.ЗагрузитьСборку("C:\Program Files (x86)\FluorineFx\Bin\net\3.5\FluorineFx.dll");
_netConnection = net.СоздатьОбъект("FluorineFx.Net.NetConnection");
ObjectEncoding = net.ПолучитьТип("FluorineFx.ObjectEncoding");
_netConnection.ObjectEncoding = ObjectEncoding.AMF3;
_netConnection.Connect("http://127.0.0.1/instrument/eOrder/Amfphp/index.php");
Платформа возвращает исключение среды выполнения:
Ошибка в методе Connect Не найден метод "FluorineFx.Net.NetConnection.Connect". mscorlib
Выясним причину этой ошибки. В исходном коде библиотеки .NET сигнатура метода выглядит следующим образом:
public void Connect(string command, params object[] arguments)
Спецификатор params является синтаксическим сахаром языка C#. При компиляции он разворачивается в ожидание массива объектов System.Object[]. Механизм позднего связывания и диспетчеризации COM-обертки при передаче только одной строки пытается найти перегрузку метода с одним строковым аргументом Connect(string). Так как в сборке объявлен метод с двумя параметрами (строка и массив), поиск метода завершается неудачей.
Для успешного вызова метода необходимо явно сформировать и передать второй параметр — массив объектов нулевой длины. Рассмотрим два способа реализации.
Способ 1. Создание типизированного пустого массива
Сформируем массив нулевого размера типа System.Object средствами используемой компоненты и передадим его вторым аргументом:
net.УстЭтоСемерка();
// Создаем пустой массив типа System.Object
аргументы = net.СоздатьМассив("System.Object", 0);
// Вызываем метод с передачей обоих параметров
_netConnection.Connect("http://127.0.0.1/instrument/eOrder/Amfphp/index.php", аргументы);
Обратите внимание на вызов метода net.УстЭтоСемерка(): в среде 1С 7.7 отсутствует нативный тип Int32, и данный флаг переключает внутренние механизмы компоненты на корректную работу с числовыми типами семерки.
Способ 2. Использование универсального метода вызова
Если в компоненте поддерживается метод ВыполнитьМетод, рефлексивный вызов можно выполнить напрямую, передав объект, имя вызываемой функции и параметры:
net.ВыполнитьМетод(_netConnection, "Connect", "http://127.0.0.1/instrument/eOrder/Amfphp/index.php");
После вызова метода Connect соединение не возвращает результат синхронно. Библиотека FluorineFx проектировалась для асинхронного взаимодействия, поэтому статус подключения передается через события NetStatus, OnConnect и OnDisconnect.
В 1С 7.7 подписка на события объектов .NET реализуется через внешнюю компоненту взаимодействия с глобальным контекстом AddIn.GlobalContext1C и генерацию класса-обертки. Проанализируем схему подключения событий:
СоздатьОберткуДляСобытий77.ОбработкаВнешнегоСобытия для приема системных уведомлений.Посмотрим на практический пример кода формы или обработки:
Перем врап, ОберткаСобытий, _netConnection;
Функция СоздатьОбертку(ОбертываемыйОбъект)
ПодключитьВнешнююКомпоненту("AddIn.GlobalContext1C");
объект = СоздатьОбъект("AddIn.GlobalContext1C");
ГлобальныйКонтекст = объект.ГлобальныйКонтекст;
ОберткаСобытий = врап.СоздатьОберткуДляСобытий77(ОбертываемыйОбъект, ГлобальныйКонтекст);
КонецФункции
Функция NetStatus()
Сообщить("Событие NetStatus: " + врап.ВСтроку(ОберткаСобытий.NetStatus));
КонецФункции
Функция OnConnect()
Сообщить("Событие OnConnect: " + врап.ВСтроку(ОберткаСобытий.OnConnect));
КонецФункции
Функция OnDisconnect()
Сообщить("Событие OnDisconnect: " + врап.ВСтроку(ОберткаСобытий.OnDisconnect));
КонецФункции
Функция ОшибкаСобытия()
ПоследняяОшибка = ОберткаСобытий.ПоследняяОшибка;
Сообщить("Ошибка в событии " + ПоследняяОшибка.Событие + ": " + врап.ВСтроку(ПоследняяОшибка.Исключение));
КонецФункции
Процедура ОбработкаВнешнегоСобытия(Источник, ИмяСобытия, Данные)
Если Источник = "FluorineFx_Net_NetConnection" Тогда
Шаблон("[" + ИмяСобытия + "()]");
КонецЕсли;
КонецПроцедуры
Процедура ПриОткрытии()
врап = СоздатьОбъект("NetObjectToIDispatch45");
врап.УстЭтоСемерка();
КонецПроцедуры
Процедура ПодключитьсяКСерверу()
ПутьКСборке = "C:\Program Files (x86)\FluorineFx\Bin\net\3.5\FluorineFx.dll";
врап.ЗагрузитьСборку(ПутьКСборке);
NetConnection = врап.ПолучитьТипИзСборки("FluorineFx.Net.NetConnection", ПутьКСборке);
_netConnection = врап.СоздатьОбъект(NetConnection);
// Создаем обертку до вызова сетевых методов
СоздатьОбертку(_netConnection);
ObjectEncoding = врап.ПолучитьТип("FluorineFx.ObjectEncoding");
_netConnection.ObjectEncoding = ObjectEncoding.AMF3;
аргументы = врап.СоздатьМассив("System.Object", 0);
_netConnection.Connect("http://127.0.0.1/instrument/eOrder/Amfphp/index.php", аргументы);
// Метод Close() вызывать сразу нельзя, иначе соединение закроется до получения ответа
КонецПроцедуры
Следующая сложность при использовании метода Call заключается в получении возвращаемых бизнес-данных. Сигнатура вызова удаленной процедуры в FluorineFx выглядит так:
_netConnection.Call("Service.Method", new CallbackHandler(), new object[] { "параметр" });
Второй параметр метода ожидает объект, реализующий интерфейс IPendingServiceCallback с методом void ResultReceived(IPendingServiceCall call). Встроенный язык 1С 7.7 не поддерживает создание классов и непосредственную реализацию интерфейсов .NET. Попытка передать объект 1С напрямую вызовет ошибку несовместимости типов.
Для преодоления этого ограничения существуют следующие архитектурные подходы:
IPendingServiceCallback, вызывает асинхронный метод, ожидает ответ с помощью объектов синхронизации (ManualResetEvent) и возвращает готовый результат в 1С синхронно (например, в виде строки JSON или XML). Это самый стабильный и рекомендуемый способ.CSharpCodeProvider средствами компоненты враппера прямо из текста модуля 1С.MSXML2.ServerXMLHTTP или WinHttp.WinHttpRequest.5.1, минуя сложности с бинарным протоколом и многопоточностью.