Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux

04.07.16

Разработка - Языки и среды

С выходом .Net Core CLR стало возможным использование классов .Net не только на Windows, но и других операционных системах. Это особенно важно в разрезе импортозамещения. И главное - это аналог COM под Linux. Сейчас под Linux для расширения возможностей 1С используются Web сервисы. Данная разработка позволит использовать не только сборки входящие в состав .Net Core, но и пользовательские портативные сборки.

Являясь автором Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент, я часто слышал в свой адрес, что это все туфта, ибо не кроссплатформенна.  Кроме того, под Windows полно готовых COM библиотек и несложно сделать свои COM библиотеки на разных языках. Для Linux ситуация сложнее. Там нет COM, а технология .Native API не слишком-то и дружелюбна.

Поэтому было решено, используя Native API, сделать ВК, которая будет взаимодействовать с .Net библиотекой для использования классов .Net в 1С. Следует учесть, что .Net Core CLR пока только на начальном пути, и многое недоступно, что есть в большом .Net, но даже того, что есть, достаточно для расширения возможностей 1С.

Одним из недостатком Native API является то, что мы не можем возвратить ВК и передать параметры ВК в метод ВК. Поэтому пришлось возвращать ссылку на объект в виде строки. И создавать методы для обертки ВК над строкой.

Не буду описывать внутренности ВК. Описание и исходники можно посмотреть 

Кроссплатформенное использование классов .Net из неуправляемого кода. Или аналог IDispatch на Linux

Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux

 

Там же можно скачать и исходники.  

Сначала определим вспомогательные методы для создания объектоа типов и обертки.

 

Перем   Врап,СсылкаНаДомен;

Функция Ъ(Ссылка)
	
	// Создаем объект по ссылке полученной из методов .Net классов
	//Физически это строка ёЁ<Ьъ>№_%)Э?&2 содержащее 12 символов для отделения их от других строк
	//и индекс в спике исполуемых объектов на стороне .Net

	рез = Новый("AddIn.NetObjectToNative.NetObjectToNative");
	// И установим ссылку
	рез.УстановитьСсылку(Ссылка);    
	возврат  рез
КонецФункции // СоздатьОбъектПоСсылке()

// Сокращенное использование метода ВК Новый
// Создает объект по строковому представлению типа или по ссылке на тип
Функция ъНовый(стр)
	возврат ъ(Врап.Новый(стр));
КонецФункции

// Сокращенное использование метода ВК ПолучитьТип
// Создает получает тип по строковому представлению типа 
Функция ъТип(стр)
	возврат ъ(Врап.ПолучитьТип(стр));
КонецФункции



Процедура ПриОткрытии() 
	
	// Установим отчет рядом с  AddInNetObjectToNative.dll
	// NetObjectToNative.dll
	// и библиотеками  Microsoft.NETCore.App\1.0.0\	
	// Так как нужны 32 разрядные так как клиент 1С 32 разрядный
	// Скачать можно здесь https://github.com/dotnet/cli
	// На сервере можно использовать 64 разрядную Core Clr
	
	Файл=Новый Файл(ЭтотОбъект.ИспользуемоеИмяФайла);  
	КаталогОтчета=Файл.Путь;	
	
	ИмяФайла=КаталогОтчета+"\AddInNetObjectToNative.dll";
	
	ПодключитьВнешнююКомпоненту(ИмяФайла, "NetObjectToNative",ТипВнешнейКомпоненты.Native); 
	Врап = Новый("AddIn.NetObjectToNative.LoaderCLR");
	CoreClrDir=КаталогОтчета+"\bin\";
	ДиректорияNetObjectToNative=КаталогОтчета;
	
	СсылкаНаДомен=Врап.СоздатьОбертку(CoreClrDir,ДиректорияNetObjectToNative,"");
	Врап.ЗагрузитьDLL(ИмяФайла);
	
	
КонецПроцедуры

 Я создал каталог, в который положил библиотеки

AddInNetObjectToNative.dll это сама ВК

NetObjectToNative.dll это .Net библиотека для получения классов .Net из .Net

TestDllForCoreClr.dll это тестовая сборка для загрузки её в пространство .Net и использования класса и его методов и свойств.

Кроме того, в папке Bin\ лежит сам .Net Core Clr, который можно скачать отсюда 

.NET Core Installers and Binaries

Ну вот он, долгожданный миг, когда можно наконец-то использовать классы .Net Core CLR.

Заодно проверим передаваемые типы.

СБ=ъ(Врап.Новый("System.Text.StringBuilder","Первая Строка"));
	CultureInfo=ъТип("System.Globalization.CultureInfo");
	
	CultureInfoES=ъ(Врап.Новый(CultureInfo.ПолучитьСсылку(),"es-ES"));
	
	
	Сообщить(СБ.Capacity);
	Сообщить(СБ.ПолучитьСсылку());
	
	InvariantCulture=ъ(CultureInfo.InvariantCulture);
	
	// К сожалению 1С вызывает метод имеющий возвращаемое значение как функцию даже если вызов идет как процедура
	//Нужно очистить ссылку в списке объектов
	ссылка=Сб.Append("Новая Строка"); Врап.ОчиститьСсылку(ссылка);
	ссылка=Сб.AppendLine();   Врап.ОчиститьСсылку(ссылка);
	ссылка=Сб.Append("Вторая Строка"); Врап.ОчиститьСсылку(ссылка);
	ссылка=Сб.AppendLine();     Врап.ОчиститьСсылку(ссылка);
	
	ссылка=Сб.AppendFormat("AppendFormat {0}, {1}, {2}, {3}, {4},", "Строка", 21, 45.89, ТекущаяДата(),истина );   Врап.ОчиститьСсылку(ссылка);
	ссылка=Сб.AppendLine(); Врап.ОчиститьСсылку(ссылка);
	
	// Так как в параметрах можно передавать только простые типы закодирум ссылку на объект в строку
	ссылка=Сб.AppendFormat(CultureInfoES.ПолучитьСсылку(),"AppendFormat {0}, {1}, {2}, {3}, {4},", "Строка", 21, 45.89, ТекущаяДата(),истина );  Врап.ОчиститьСсылку(ссылка);
	ссылка=Сб.AppendLine(); Врап.ОчиститьСсылку(ссылка);
	
	ссылка=Сб.AppendFormat(InvariantCulture.ПолучитьСсылку(),"AppendFormat {0}, {1}, {2}, {3}, {4},", "Строка", 21, 45.89, ТекущаяДата(),истина ); 
	
	Сообщить(СБ.ToString());
	Сообщить("Ёмкостъ ="+СБ.Capacity);
	// Увеличим емкость
	СБ.Capacity=СБ.Capacity+40;
	Сообщить("Новая Ёмкостъ ="+СБ.Capacity);
	
	// Очистка ссылок СБ и  СultureInfo осуществляется внутри ВК

Теперь перейдем к более сложным классам. А именно HTTPClient с возможностью сжатия трафика


 
// Вставить содержимое обработчика.
	//	System.Net.Http, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
	
	
	// Создадим HttpClient и вызовем Get запрос используя сжатие трафика 
	// На данный момент я не нашел как получить загруженные сборки или как загрузить сборку по имени файла
	// Поэтому загружаем по полному имени
	HttpClient=ъТип("System.Net.Http.HttpClient, System.Net.Http, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
	HttpClientHandler = ъТип("System.Net.Http.HttpClientHandler, System.Net.Http, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
	DecompressionMethods= ъТип("System.Net.DecompressionMethods, System.Net.Primitives, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
	
	
	handler = ъНовый(HttpClientHandler.ПолучитьСсылку());
	// Можно использовать и так. Только Не соберем ссылки
	//handler.AutomaticDecompression=Врап.OR(DecompressionMethods.GZip,DecompressionMethods.Deflate);
	
	ссылкаGZip=DecompressionMethods.GZip;
	ссылкаDeflate=DecompressionMethods.Deflate;
	
	// В 1С нет бинарных операция. Для этого на стороне .Net есть функция
	handler.AutomaticDecompression=Врап.OR(ссылкаGZip,ссылкаDeflate);
	Врап.ОчиститьСсылку(ссылкаGZip);   Врап.ОчиститьСсылку(ссылкаDeflate);
	
	Клиент = ъ(Врап.Новый(HttpClient.ПолучитьСсылку(),handler.ПолучитьСсылку()));
	
	uriSources ="https://msdn.microsoft.com/en-us/library/system.net.decompressionmethods(v=vs.110).aspx";
	
	Стр=ъ(Клиент.GetStringAsync(uriSources)).Result;
	Сообщить(СтрДлина(стр));

Ух ты, и это работает!

Еще одна особенность Native API в том, что мы можем получить двоичные данные, но вот передать их в параметры метода метода ВК нет.

Дальше идет проверка вызова сторонней библиотеки и работа с двоичными данными.


 
Тестовый=ъТип("TestDllForCoreClr.Тестовый, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
	Тест=ъ(Врап.Новый(Тестовый.ПолучитьСсылку()," Свойство из Конструктора"));
	Сообщить(Тестовый.Поле);
	Тестовый.Поле="Установка из 1С";
	Сообщить(Тестовый.Поле);
	
	Сообщить(Тест.СвойствоОбъекта);
	
	Тест.СвойствоОбъекта=("Установлено Свойство из 1С");
	Сообщить(Тест.СвойствоОбъекта);
	Сообщить(Тест.ПолучитьСтроку());
	
	
	Врап.ДвоичныеДанныеКакОбъект=истина;
	ДД=Тест.ПолучитьДвоичныеДанные();
	UnicodeEncoding= ъНовый("System.Text.UnicodeEncoding, System.Text.Encoding.Extensions, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
	//Если не установить Врап.ДвоичныеДанныеКакОбъект=истина;
	//То при вызове  UnicodeEncoding.GetString(ДД);
	// 1С выдает ошибку
	// Неверный аргумент
	
	СтрокаИзДД=UnicodeEncoding.GetString(ДД);
	Сообщить(СтрокаИзДД);

 

Самое главное, что мы можем использовать сторонние библиотеки, которые должны лежать рядом с NetObjectToNative.dll

К сожалению, в отличие от COM в .Native ВК мы не можем использовать энумераторы

 Для Каждого Элемент ИЗ Списка Цикл

 

Поэтому для упрощения использования массивов и списков создана функция ПолучитьЭнумератор


 
Функция ПолучитьЭнумератор(Объект)
	
	Перечислимый=ъ(Врап.ПолучитьИнтерфейс(Объект.ПолучитьСсылку(),"IEnumerable"));
	ПеречислительСсылка=Перечислимый.GetEnumerator();
	// На всякий случай приведем к Интерфейсу IEnumerator
	Перечислитель=ъ(Врап.ПолучитьИнтерфейс(ПеречислительСсылка,"IEnumerator"));
	Врап.ОчиститьСсылку(ПеречислительСсылка);	
	// Можно и так
	//IEnumerable=ъТип("System.Collections.IEnumerable");
	//IEnumerator=ъТип("System.Collections.IEnumerator")
	// Перечислимый=ъ(Врап.ПолучитьИнтерфейс(Объект.ПолучитьСсылку(),IEnumerable));
	//ПеречислительСсылка=Перечислимый.GetEnumerator();
	// На всякий случай приведем к Интерфейсу IEnumerator
	// Перечислитель=ъ(Врап.ПолучитьИнтерфейс(ПеречислительСсылка,IEnumerator));
	//Врап.ОчиститьСсылку(ПеречислительСсылка);	
	
	возврат  Перечислитель
КонецФункции // ПолучитьЭнумератор()

Процедура ТестЭнумератораНажатие(Элемент)
	List=ъТип("System.Collections.Generic.List`1[System.String]");
	
	Список=ъНовый(List.ПолучитьСсылку());
	Для сч=1 По 10 Цикл
		Список.Add(строка(сч));    
	КонецЦикла; 
	
	// Получим энумератор через соответствующие интерфейсы
	// Заодно проверим  метод ПолучитьИнтерфейс
	СписокЭнум=ПолучитьЭнумератор(Список);
	
	Пока СписокЭнум.MoveNext() Цикл
		//  Врап.ВСтроку вывоит строковое представление всех типов в том числе числовые, строки, неопределено
		Сообщить(СписокЭнум.Current);
		
	КонецЦикла; 
	
	// Получение Энумератора из ВК
	СписокЭнум2=ъ(Врап.ПолучитьЭнумератор(Список.ПолучитьСсылку()));
	
	Пока СписокЭнум2.MoveNext() Цикл
		//  Врап.ВСтроку вывоит строковое представление всех типов в том числе числовые, строки, неопределено
		Сообщить(СписокЭнум2.Current);
		
	КонецЦикла; 
	
КонецПроцедуры

Теперь перейдем к более грустному.
В этой статье был тест скорости, время вызова которого составляло более 300 000 вызовов в секунду.

Проведем аналогичный тест на 1С:


 
Функция ПолучитьЧисло(зн)
	возврат зн;	
КонецФункции // ()

Процедура ТестСкорости2Нажатие(Элемент)
	// Вставить содержимое обработчика.
	КоличествоИтераций=200000;
	Тестовый=ъТип("TestDllForCoreClr.Тестовый, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
	Тест=ъ(Врап.Новый(Тестовый.ПолучитьСсылку()," Свойство из Конструктора"));
	
	stopWatch = ъНовый("System.Diagnostics.Stopwatch,System.Runtime.Extensions, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
	
	стр="";
	Тест.ПолучитьЧисло(1);
	
	НачВремя=ТекущаяДата();
	stopWatch.Start();
	
	
	Для сч=1 по КоличествоИтераций Цикл
		Тест.ПолучитьЧисло(сч);
		
	КонецЦикла;
	
	stopWatch.Stop();
	
	ВремяВыполнения=ТекущаяДата()-НачВремя;
	Сообщить("ПолучитьЧисло ="+ВремяВыполнения);
	ВывестиВремя(stopWatch);
	
	
	НачВремя=ТекущаяДата();
	stopWatch.Restart();
	
	
	Для сч=1 по КоличествоИтераций Цикл
		ПолучитьЧисло(сч);
		
	КонецЦикла;
	
	stopWatch.Stop();
	
	ВремяВыполнения=ТекущаяДата()-НачВремя;
	Сообщить("ПолучитьЧисло ="+ВремяВыполнения);
	ВывестиВремя(stopWatch);
	
КонецПроцедуры

 

00:00:09.63  Для .Net
00:00:01.23  Для 1С

 

00:00:09.93 Для .Net
00:00:01.20 Для 1С

То есть скорость вызова уменьшилась до  20 000 вызовов в секунду.
Но и этого достаточно, так обычно вызываются более тяжелые методы.


Добавил поддержку IDynamicMetaObjectProvider (DynamicObject,ExpandoObject).  В исходниках есть примеры. Это важно при использовании различного рода парсеров


Теперь стоит поговорить о недостатках 1С реализации Технологии Внешних Компонент.

1. Абсолютно не нужны методы FindMethod, FindProp, IsPropReadable, IsPropWritable, GetNParams, HasRetVal, GetParamDefValue

Так как у методов

bool CallAsProc

bool CallAsFunc

bool SetPropVal и bool GetPropVal есть возвращаемое значение об успешном выполнении

Информация об ошибке возвращается через AddError.

Да и вызов по индексу это анахронизм от IDiapatch, где было описание диспинтерфейсов для увеличения скорости вызова.

2. При возвращении методами SetPropVal и GetPropVal исключение не вызывается

3. Зачем-то происходит установка свойств там, где в коде этого не требуется.

4. Вызывается метод как функция там, где метод вызывается как процедура.

5. Один из основных - это нельзя вернуть и передать экземпляр ВК из методов ВК.

Я лично не вижу никаких проблем. Определить значение для такого типа и установить ссылку в поле pInterfaceVal.

Подсчет ссылок происходит на стороне 1С. Передавать можно в том числе и объекты 1С только на время вызова метода.

В дальнейшем можно развить до использования событий объектов .Net в 1С по примеру .NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия

Использовать асинхронные вызовы по примеру ".Net в 1С. Асинхронные HTTP запросы, отправка Post нескольких файлов multipart/form-data, сжатие трафика с использованием gzip, deflate, удобный парсинг сайтов и т.д."

Вообще интеграция .Net есть в Microsoft Dynamics AX ClrObject.

Используя кроссплатформенный Core Clr, можно интегрировать в 1С. Особенно это актуально для Linux как импортозамещения.

Пока проверил, работает на Windows 7,10. Linux и IOS пока нет, но в скором проверю на виртуальной машине. .Net Core CLR можно скачать здесь

С чем я бы с удовольствием помог 1С. Есть огромный опыт использования классов .Net в 1С.

.Net C# кроссплатформенный .Net Core

См. также

Зачем нам 1С:Элемент

Мобильная разработка Языки и среды Бесплатно (free)

Flutter может быть использован с 1С:Предприятием для разработки кроссплатформенных мобильных приложений, обеспечивая единый интерфейс и функциональность на устройствах под управлением iOS и Android. Это позволяет создавать приложения с высокой производительностью благодаря использованию собственного движка рендеринга Flutter. Интеграция Flutter с 1С:Предприятием позволяет создавать мобильные приложения любого уровня сложности, интегрировать их в корпоративные информационные системы, а также реализовывать бизнес-логику

19.03.2024    6861    ROk_dev    56    

37

(Не) Строгая типизация 1С

Языки и среды Платформа 1С v8.3 Бесплатно (free)

Существует множество языков программирования, и каждый имеет свои особенности по работе с типами данных. Слабые, явные, динамические и другие... Но кто же здесь 1С и почему с приходом "строгой" типизации EDT 1С-программистам стоит задуматься над изменением своих привычек.

16.01.2024    4218    SeiOkami    21    

55

Простое приложение на Dart

Языки и среды Бесплатно (free)

Пример небольшого приложения, с которого можно начать изучать язык программирования Dart.

08.08.2023    3194    acvatoris    6    

13

Статический анализатор кода 1С на Си

Языки и среды Платформа 1С v8.3 Россия Бесплатно (free)

Написание статического анализатора для 1С традиционным способом на Си.

30.06.2023    2982    prohorp    15    

12

Сквозная задача на Исполнителе - часть первая (IMAP)

Языки и среды Абонемент ($m)

Поставили нам задачу - вынести на отдельный сервер функционал получения заказов от клиентов по электронной почте, парсинг полученных XLS в приемлемый вид и трансформация заказов в красивый JSON, понятный нашей учетной системе на 1С. Всю эту красоту желательно запустить в отдельном докер - контейнере, по возможности не тратя лицензии, поэтому отдельно стоящую конфигурацию на БСП отвергаем сразу. Можно было бы собрать всё на Apache Airflow или Apache NiFi, но решили попробовать реализовать всю логику без Open Source, будем делать свой ETL, с Исполнителем, который в версии 3.0 научился взаимодействовать с электронной почтой по IMAP. Начнем с середины - сначала напишем скрипты, а потом соберем их в рабочую конструкцию

1 стартмани

01.06.2023    1895    0    kembrik    2    

7

1С# - Расширяем код 1С кодом на C#

Языки и среды Инструментарий разработчика Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Вставки кода на C# внутри кода на 1С.

7 стартмани

07.04.2023    9286    4    SerVer1C    56    

43

Независимая разработка совместимых компонент на ORM 1С – миф или истина где-то в аннотациях Java?

Языки и среды Платформа 1С v8.3 Бесплатно (free)

При работе с 1С ORM (object relation mapping) все время преследует ощущение постоянного создания монолитного приложения — один раз привязался к какой либо сущности (например, справочник Контрагенты), и весь код заполнен ссылками на эту конкретную реализацию. Можно ли независимо разрабатывать в ORM совместимые между собой справочник «Контрагентов» и использующий его документ «Платежное поручение», но при этом избежать жестких зависимостей? Спасут ли нас микросервисы? Пример на аннотациях Java демонстрирует, как это возможно делать.

13.03.2023    1024    1CUnlimited    0    

2

xPath в 1С

Файловый обмен (TXT, XML, DBF), FTP Языки и среды Платформа 1С v8.3 Бесплатно (free)

Опыт работы методами языка xPath в 1С.

04.03.2023    4937    DemetrKlim    40    

46
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. kiv1c 809 06.07.16 14:25 Сейчас в теме
Скажите, а таки чем вы руководствуетесь когда называете функции "Ъ", "Ъновый" и "Ътип" ???
Drivingblind; SShipilov; baracuda; ётун; +4 Ответить
2. Serginio 938 06.07.16 14:52 Сейчас в теме
Чтобы было сокращенно и было созвучно с Новый , а Ътип из той же оперы.
Мне лично, так код удобнее читать.
L0z4; albert.goncharov; +2 Ответить
3. pbazeliuk 1955 06.07.16 20:22 Сейчас в теме
Плюс за старания. Но по опыту скажу, если совмещать высокую нагрузку с внешними компонентами, до добра это не доводит.
5. Serginio 938 06.07.16 21:35 Сейчас в теме
(3) pbazeliuk,
Проблема тут не в самой компоненте, а интерфейсе, что 1С предоставляет.

Например практически все программисты 1С используют ComОбъект.

По моей методе можно использовать
NetОбъект,NetТип
JavaОбъект,JavaТип

И эти объявления будут реально кроссплатформенны.
При это различия с ComОбъект минимальны. Имя класса равноценно комовскому ProgID. При этом нет ограничений на используемые типы.
Ты можешь написать свою библиотеку поместить в определенное место и использовать её вместо COM. Без регистрации итд. Расширять возможности 1С станет легче.

Например сейчас в конфигураторе куча функций, которые есть в стандартных библиотеках. При этом функционал 1С функций сильно недотягивает до стандартных библиотек.
Учитывая кроссплатформенность можно использовать нетовские или явовские библиотеки везде где можно. Упрощая программирование.
А что касается работы с HTTP,SMPT, JSON то эти библиотеки были задолго до того как 1С их реализовывала, при этом с ошибками и функционалом сильно недотягивающих до .Net или Java.
Стоит ли тратить время на то, что можно взять из стандартных библиотек. А ведь можно легко расширить за счет своих сборок.

При этом например нетовская библиотека весит всего 65 мегабайт, которую можно включить в дистрибутив и главное это кроссплатформенное решение. Причем нет ничего сложного передавать в параметрах и объекты 1С которые поддерживают аналогичный интерфейс. Можно пойти по пути подсчета ссылок в 1С, а доступ к объектам 1С только на время вызова метода ВК.

Например Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент многие бы использовали на равне с ComОбъект, но главная причина её неприменения в том, что она неинтегрирована в 1С.

Даже если 1С не хочет интегрировать .Net в 1С, то можно сделать вариант ВК под .Net и Java . Прежде всего для получения объектов ВК и передачи их в параметрах. Кроме того можно добавить доступ по индексу [], получения итератора.
duhin; SShipilov; +2 Ответить
6. Serginio 938 06.07.16 21:37 Сейчас в теме
(3) pbazeliuk,

Кстати сейчас нашел способ вызвать методы и свойсва для Динамиков https://rsdn.ru/forum/dotnet/6493695.1
и вставлю в компоненту
4. soba 06.07.16 21:22 Сейчас в теме
Направление интересное. Пожалуй только фраза про "импортозамещение" не к месту прикреплена. Вроде Линус Торвальдс российского паспорта не получал пока. Ну и из 1с- "Энумератор" и "Врап" звучат так себе.
7. Serginio 938 06.07.16 21:40 Сейчас в теме
(4) soba,
Согласен, но меня на это сподвигло собеседование при поиске работы. Так как моя разработка
Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент
была мало интересна, так как не кроссплатформенна, а в разрезе "импортозамещения" сейчас требуется кроссплатформенное решение.
Сделал, но какого не то, что ажиотажа а даже простой заинтересованности не видно.
17. PolSerg 08.07.16 09:28 Сейчас в теме
(7) Причем здесь импортозамещение, Linux интересен прежде всего тем, что не кишит всякой заразой как винда, поэтому и тренд во многих компаниях, включая ту в которой работаю я, как бонус свободный софт, как правило, бесплатен.
18. Serginio 938 08.07.16 10:08 Сейчас в теме
(17) Если ты прочитал 7 то это не мой термин. Но, что скажешь по поводу расширения функционала 1С на Linux за счет использования классов .Net?
8. Serginio 938 06.07.16 21:53 Сейчас в теме
(4) soba, По поводу врап и Энумератор.
Лучше было бы по аналогии с ComОбъек писать NetОбъект.
Но так много писанины. На сче Энумератора, то не нашел лучшего перевода (перечислитель перечислимый)
Было бы проще если бы по аналогии с COM была поддержка Для Каждого
13. ётун 07.07.16 08:07 Сейчас в теме
(8) самое пикантное, что функция "ПолучитьЭнумератор" при этом возвращает переменную "Перечислитель". Первый звоночек - если человек не может понятно что-то назвать, то это сигнал о том, что в предметной области проблемы. Ну или несерьезное отношение.

Общее впечатление, что решается какая-то очень локальная задача, черезчур много "я", "мне", "лично". Сам придумал, сам обиделся, что 1С не такая. Направление интересное, но не больше, типа "а смотрите как я могу".
15. Serginio 938 07.07.16 10:37 Сейчас в теме
(13) ётун, >> Общее впечатление, что решается какая-то очень локальная задача

Ну если использование огромного количества стандартных библиотек .Net и расширения за счет написания своих библиотек и практически замена COM это локальная задача, то что называется глобальной?
9. Vovan58 65 06.07.16 23:01 Сейчас в теме
Идея +. А Java c CORBA - не рулят?
10. Serginio 938 06.07.16 23:17 Сейчас в теме
CORBA это Out Process, я предлагаю упрощенный In Process взаимодействие.
Сейчас линуксоиды используют HTTP или Web сервисы, это и есть аналог CORBA .
Java тоже можно прикрутить по аналогичной методе, если Java поддерживает экспорт методов в Native.
11. premierex 204 07.07.16 06:29 Сейчас в теме
(0) 5. Один из основных - это нельзя вернуть и передать экземпляр ВК из методов ВК.
Я тоже писал много внешних компонент, но вот этого реально не понял. Куда надо передавать экземпляр ВК из методов ВК?
ётун; +1 Ответить
12. Serginio 938 07.07.16 06:58 Сейчас в теме
Ты статью читал?
У ВК есть методы
УстановитьСсылку Создается ВК по строковому представлению, применяется как ъ(
ПолучитьСсылку Получается Ссылка для передачи в параметрах.

14. Serginio 938 07.07.16 09:50 Сейчас в теме
Там на самом деле два захода. Сначала получаем Энумератор, а из энумератора получаем перечислитель. Это просто проблемы перевода.
IEnumerator и IEnumerable
Смотрите не как я могу, а используй то, что я сделал. И делюсь своим опытом, на что было потрачено куча времени в том числе и на изучение предметной области.

Кроме того я просто говорю о недостатках реализации .Native ВК, которые легко исправить.
Или вообще можно интегрировать в 1С. Хуже от этого точно не будет. Но будет замена ComОбъект
16. Serginio 938 07.07.16 16:00 Сейчас в теме
Добавил поддержку объектов с поддержкой IDynamicMetaObjectProvider

Для теста создал ExpandoObject
  public object ПолучитьExpandoObject()
        {

            dynamic res = new ExpandoObject();
            res.Имя = "Тест ExpandoObject";
            res.Число = 456;
            res.ВСтроку = (Func<string>)(() => res.Имя);
            res.Сумма = (Func<int, int, int>)((x, y) => x + y);

            return res;
        }

Показать



И наследника DynamicObject

class TestDynamicObject : DynamicObject
    {

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {

            return true;
        }
        // получение свойства
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = binder.Name;
            return true;
        }
        // вызов метода
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var res = new StringBuilder("{0}(");
            var param = new object[args.Length + 1];
            param[0] = binder.Name;
            if (args.Length > 0)
            {
                Array.Copy(args, 0, param, 1, args.Length);
                for (int i = 0; i < args.Length; i++)
                {
                    res.AppendFormat("{{{0}}},", i + 1);

                }

                res.Remove(res.Length - 1, 1);

            }
            res.Append(")");

            result = String.Format(res.ToString(), param);
            return true;


        }
    }


Показать


Теперь можно вызвать на 1С

Тестовый=ъТип("TestDllForCoreClr.Тестовый, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
	Тест=ъ(Врап.Новый(Тестовый.ПолучитьСсылку()," Свойство из Конструктора"));
	
	// Это аналог структуры, но с поддержкой методов
	РасширяемыйОбъект=ъ(Тест.ПолучитьExpandoObject());
	
	Сообщить("ВСтроку="+РасширяемыйОбъект.ВСтроку());
	Сообщить("Сумма=" + РасширяемыйОбъект.Сумма(1, 2));
	
	Сообщить(РасширяемыйОбъект.Имя);
	Сообщить(РасширяемыйОбъект.Число);
	
	РасширяемыйОбъект.Имя="Новое Имя";
	РасширяемыйОбъект.Число=768;
	// Добавим новое свойство
	РасширяемыйОбъект.НовоеСвойство="Новое Свойство";
	
	Сообщить(РасширяемыйОбъект.Имя);
	Сообщить(РасширяемыйОбъект.Число);
	Сообщить(РасширяемыйОбъект.НовоеСвойство);
	
	НовыйРеквизит=ъ(Врап.Новый("System.Dynamic.ExpandoObject, System.Dynamic.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"));
	
	НовыйРеквизит.Имя="Новый Реквизит";
	НовыйРеквизит.Значение=123;
	
	
	РасширяемыйОбъект.НовыйРквизит=НовыйРеквизит.ПолучитьСсылку();
	Сообщить(ъ(РасширяемыйОбъект.НовыйРквизит).Имя);
	
	
	TestDynamicObject=ъТип("TestDllForCoreClr.TestDynamicObject, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
	
	ДинамикОбъект=ъНовый(TestDynamicObject.ПолучитьСсылку());
	ДинамикОбъект.УстановимЛюбоеСвойство="Чего то там";
	Сообщить( ДинамикОбъект.ПолучитТоЧтоПередали);
	Сообщить(ДинамикОбъект.ПолучитТоЧтоПередалиСПараметрами(1,3.45,ТекущаяДата()));

Показать




Это удобно при работе с различными парсерами
19. Serginio 938 13.07.16 15:41 Сейчас в теме
Добави вывод типов для дженерик методов
Теперь можно не выводить отдельно метод

// public T ДженерикМетод<V, T>(V param1, T param2, V param3)
Сообщить(Тест.ДженерикМетод(1,"Привет",3));
//

//public V ДженерикМетод2<K, V>(Dictionary<K, V> param1, K param2, V param3)
Словарь= ъНовый("System.Collections.Generic.Dictionary`2[System.Int32,System.String]");
Сообщить(Тест.ДженерикМетод2(Словарь.ПолучитьСсылку(),3,"Привет2"));

// public K ДженерикМетод3<K>(IList<K> param1, int param2, K param3)
List=ъНовый("System.Collections.Generic.List`1[System.String]");
Сообщить(Тест.ДженерикМетод3(List.ПолучитьСсылку(),3,"Привет3"));

Показать
20. Serginio 938 19.07.16 14:59 Сейчас в теме
Сделал поддержку внешнего события
В классе создадим пле типа Action<string, string, string>
 public class Тестовый 
    { 
      public Action<string, string, string>   ВнешнееСобытие1С;

// И сделаем эмуляцию события.



public async void TestВнешнегоСобытия() 
        { 
            for(int i=0;i<100; i++)
            {
                var значение = i.ToString();
                Task.Run(async() =>
                {
                   await Task.Delay(1000).ConfigureAwait(false);
                   this?.ВнешнееСобытие1С("Тестовый", "ТестовоеСообщение", значение);
                });

                await Task.Delay(50).ConfigureAwait(false);
            }


        } 

Показать



В 1С.

Процедура ВнешнееСобытие(Источник, Событие, Данные)
    // Вставить содержимое обработчика.

    
    Сообщить("Источник="+Источник);
    Сообщить("Событие="+Событие);
    Сообщить("Данные="+Данные);
КонецПроцедуры

Процедура ТестВнешнегоСобытияНажатие(Элемент)
    // Вставить содержимое обработчика.

    Тестовый=ъТип("TestDllForCoreClr.Тестовый, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");

Тест=ъ(Врап.Новый(Тестовый.ПолучитьСсылку()," Свойство из Конструктора")); 

Делегат=Ъ(Врап.ПолучитьДелегатВнешнегоСобытия1C());
Тест.ВнешнееСобытие1С=Делегат.ПолучитьСсылку();
Тест.TestВнешнегоСобытия();
КонецПроцедуры

Показать



И не забыть в Переменных модуля установить
Перем   Тест;
21. Serginio 938 21.07.16 14:46 Сейчас в теме
В VS 2015 апдейт 3 появилась возможность создавать библиотеки и приложения под .Net Core
Вкладка
Шаблоны->Windows->.Net Core

Такой проект отличается от портативного.
В тестах добавил пример создания JObject и сериализации его в Json

Про установку SDK и прочее можно посмотреть здесь
http://metanit.com/sharp/aspnet5/1.2.php
22. Serginio 938 27.07.16 15:18 Сейчас в теме
Добавил поддержку параметров по умолчанию
Тест вызова метода с параметрами по умолчанию
	//public static int OptionalParam(int x, int y, int z = 5, int s = 4,string str="Привет")
	//       {
	//           return x + y + z + s;
	//       }


	Сообщить("OptionalParam(int x, int y)="+Тестовый.OptionalParam(1,2));
	Сообщить("OptionalParam(int x, int y, int z = 5)="+Тестовый.OptionalParam(1,2,3));
	Сообщить("OptionalParam(int x, int y, int z = 5, int s,string str)="+Тестовый.OptionalParam(1,2,3,4,"ХаХа"));
Показать
23. par_62 22.01.19 07:47 Сейчас в теме
Все хорошо,красиво. Но мы прагматики и зададим вопрос. И он сакраментальный. Зачем?
Если 1С для Native API избрало С++ зачем использовать Net библиотеки? Есть море библиотек на С++ спокойно и хорошо работающих в ВК. Точно так же как нет смысла в СОМ на NET.
Преимуществ нет никаких,одни проблемы.
Автор проделал большую работу,теоретически интересную и прочитал я с удовольствием. Но использовать просто не для чего. Возможно,только мне лично. Без обид,просто делюсь мнением
24. Serginio 938 22.01.19 14:35 Сейчас в теме
Так ВК то тоже нужно программировать и для каждого случая своя. Да и С++ это не особо то удобный инструмент. А здесь есть одна ВК и ну и нужно знать только классы и методы. По сути то и C# знать не нужно. Только 1С.

Если бы 1С удосужились дать возможность возвращать объект типа ВК то можно было бы избавиться от Ъ, но у них своя политика.
Конечно в таком виде это использовать нельзя. А вот Использование классов .Net в 1С для новичков многие используют. Ну и как я понял линукс используют единицы
25. victor_goodwill 46 17.01.20 12:19 Сейчас в теме
Очень интересная тема с точки зрения кроссплатформенности. Можете подсказать (при беглом просмотре не увидел), где есть указание того, как правильно запустить подключение Net под Linux из 1С? Есть ли какая-то инструкция или ссылка на документацию, где почитать что установить и как настроить, как создать класс? Мы хотели бы сделать замену Новый COMОбъект("ADODB.Connection") для доступа к базе MS Sql с сервера Linux
26. victor_goodwill 46 17.01.20 12:24 Сейчас в теме
Видел в примерах в другой статье такие конструкции:
27. victor_goodwill 46 17.01.20 12:24 Сейчас в теме
connection = new Net.System.Data.SqlClient.SqlConnection(ConnectionString);
command = new Net.System.Data.SqlClient.SqlCommand(ТекстЗапроса,connection);
28. Serginio 938 17.01.20 12:34 Сейчас в теме
Давно это писалось еще под .Net Core 1
В этой статье есть ссылки
https://habr.com/ru/post/304482/

Но многие уже не работают.

https://docs.microsoft.com/ru-ru/dotnet/core/tutorials/netcore-hosting

Вот этот недавно изменяли
https://github.com/dotnet/coreclr/blob/master/src/dlls/mscoree/unixinterfac­e.cpp

https://github.com/dotnet/coreclr/issues/22271
29. victor_goodwill 46 17.01.20 16:13 Сейчас в теме
Спасибо, будем разбираться!
31. victor_goodwill 46 20.01.20 13:07 Сейчас в теме
(28) Подскажите, у вас был опыт тестирования вашей компоненты именно под Linux?
30. Serginio 938 17.01.20 16:56 Сейчас в теме
Вот здесь примеры подключния к Ado
https://infostart.ru/public/544232/

СборкаSqlClient=ъ(Врап.Сборка("System.Data.SqlClient.dll"));
    SqlConnection=ъ(СборкаSqlClient.GetType("System.Data.SqlClient.SqlConnection"));
    SqlCommand=ъ(СборкаSqlClient.GetType("System.Data.SqlClient.SqlCommand")); 
    
    connection =ъ(Врап.Новый(SqlConnection.ПолучитьСсылку(),ConnectionString));
    connection.Open();
    
    ТекстЗапроса = "Sel ect Номенклатура.DESCR Наименование  Fr om sc84 Номенклатура where DESCR Like '%'+@Строка+'%'
    |order by Номенклатура.DESCR";
    
    
    command = ъ(Врап.Новый(SqlCommand.ПолучитьСсылку(),ТекстЗапроса,connection.ПолучитьСсылку()));
    
    Parameters=ъ(command.Parameters);
    Parameters.AddWithValue("@Строка", "ДСП");
    dr = ъ(command.ExecuteReader());
    
    Пока dr.Read() Цикл
        Сообщить(dr.get_Item("Наименование"));
    КонецЦикла;
Показать
32. victor_goodwill 46 21.01.20 15:55 Сейчас в теме
Попытались скомпилировать компоненту под Linux и столкнулись с вызовами чистого Win API - LoadLibrary. Получается, что кросс-платформенность не поддерживается?
33. Serginio 938 24.01.20 12:42 Сейчас в теме
Ну когда я делал не было нужды в линуксе.
Нужно добавить условную компиляцию и
используя данную статью https://docs.microsoft.com/ru-ru/dotnet/core/tutorials/netcore-hosting
использовать dlopen (в Linux или macOS).

Шаг 1. Поиск и загрузка CoreCLR

Интерфейсы API среды выполнения .NET Core находятся в coreclr.dll (в Windows), в libcoreclr.so (на платформе Linux) или в libcoreclr.dylib (в macOS). Первым шагом для размещения .NET Core является загрузка библиотеки CoreCLR. Некоторые основные приложения проверяют разные пути или используют входные параметры для поиска библиотеки, пока другие могут загрузить ее по заранее определенному пути (рядом с основным приложением, например, или из известного расположения на компьютере).
После обнаружения библиотека загружается с помощью LoadLibraryEx (в Windows) или dlopen (в Linux или macOS).
35. sh00m 46 17.10.22 20:31 Сейчас в теме
(33)
Serginio, отец, это, видимо никому кроме вас не под силу, подмогните пожалуйста, заставьте ваш метод работать под Linux ,,,
34. sh00m 46 08.08.22 20:05 Сейчас в теме
а нет ли наработок как это все заставить заработать под .NET 6.0 ?

[UPD] Поотвечаю сам себе, качаем https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/sdk-6.0.302-windows-x64-binaries а то, что у автора лежит в \src\ лежит в скаченном архиве по пути: "dotnet-sdk-6.0.302-win-x64\shared\Microsoft.NETCore.App\6.0.7\"

[UPD2] Получилось у меня пересобрать под современной visual studio 2022 проекты NetObjectToNative (.NET 6.0) и AddInNetObjectToNative, а вот что с ними делать под linux чтобы заставить 1С использовать свою DLL, как я это делаю с помощью NetObjetToIDispatch45 сейчас под виндой - совершенно не понятно :) Свою DLL переписал под .NET 6.0, опубликовал в виде nuget-пакета со всеми зависимостями... продолжаю рыть ...
36. Serginio 938 19.10.22 12:14 Сейчас в теме
(34) Сейчас совершенно нет времени.
Нужно переделать согласно новому апи описанному в (33)
Суть получить ссылки на статические методы .Net

Более подробно по C++ можно посмотреть здесь https://habr.com/ru/post/304542/

А для начала разобраться с https://habr.com/ru/post/304482/
Оставьте свое сообщение