gifts2017

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

Опубликовал Сергей Смирнов (Serginio) в раздел Программирование - Практика программирования

С выходом .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С.

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Иван Коротеев (kiv1c) 06.07.16 14:25
Скажите, а таки чем вы руководствуетесь когда называете функции "Ъ", "Ъновый" и "Ътип" ???
baracuda; ётун; +2 Ответить
2. Сергей Смирнов (Serginio) 06.07.16 14:52
Чтобы было сокращенно и было созвучно с Новый , а Ътип из той же оперы.
Мне лично, так код удобнее читать.
3. Петр Базелюк (pbazeliuk) 06.07.16 20:22
Плюс за старания. Но по опыту скажу, если совмещать высокую нагрузку с внешними компонентами, до добра это не доводит.
4. soba (soba) 06.07.16 21:22
Направление интересное. Пожалуй только фраза про "импортозамещение" не к месту прикреплена. Вроде Линус Торвальдс российского паспорта не получал пока. Ну и из 1с- "Энумератор" и "Врап" звучат так себе.
5. Сергей Смирнов (Serginio) 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 . Прежде всего для получения объектов ВК и передачи их в параметрах. Кроме того можно добавить доступ по индексу [], получения итератора.
6. Сергей Смирнов (Serginio) 06.07.16 21:37
(3) pbazeliuk,

Кстати сейчас нашел способ вызвать методы и свойсва для Динамиков https://rsdn.ru/forum/dotnet/6493695.1
и вставлю в компоненту
7. Сергей Смирнов (Serginio) 06.07.16 21:40
(4) soba,
Согласен, но меня на это сподвигло собеседование при поиске работы. Так как моя разработка
Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент
была мало интересна, так как не кроссплатформенна, а в разрезе "импортозамещения" сейчас требуется кроссплатформенное решение.
Сделал, но какого не то, что ажиотажа а даже простой заинтересованности не видно.
8. Сергей Смирнов (Serginio) 06.07.16 21:53
(4) soba, По поводу врап и Энумератор.
Лучше было бы по аналогии с ComОбъек писать NetОбъект.
Но так много писанины. На сче Энумератора, то не нашел лучшего перевода (перечислитель перечислимый)
Было бы проще если бы по аналогии с COM была поддержка Для Каждого
9. Vladimir Glumov (Vovan58) 06.07.16 23:01
Идея +. А Java c CORBA - не рулят?
10. Сергей Смирнов (Serginio) 06.07.16 23:17
CORBA это Out Process, я предлагаю упрощенный In Process взаимодействие.
Сейчас линуксоиды используют HTTP или Web сервисы, это и есть аналог CORBA .
Java тоже можно прикрутить по аналогичной методе, если Java поддерживает экспорт методов в Native.
11. Максим *** (premier) 07.07.16 06:29
(0) 5. Один из основных - это нельзя вернуть и передать экземпляр ВК из методов ВК.
Я тоже писал много внешних компонент, но вот этого реально не понял. Куда надо передавать экземпляр ВК из методов ВК?
ётун; +1 Ответить
12. Сергей Смирнов (Serginio) 07.07.16 06:58
Ты статью читал?
У ВК есть методы
УстановитьСсылку Создается ВК по строковому представлению, применяется как ъ(
ПолучитьСсылку Получается Ссылка для передачи в параметрах.

13. Имя Фамилия (ётун) 07.07.16 08:07
(8) Serginio, самое пикантное, что функция "ПолучитьЭнумератор" при этом возвращает переменную "Перечислитель". Первый звоночек - если человек не может понятно что-то назвать, то это сигнал о том, что в предметной области проблемы. Ну или несерьезное отношение.

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

Кроме того я просто говорю о недостатках реализации .Native ВК, которые легко исправить.
Или вообще можно интегрировать в 1С. Хуже от этого точно не будет. Но будет замена ComОбъект
15. Сергей Смирнов (Serginio) 07.07.16 10:37
(13) ётун, >> Общее впечатление, что решается какая-то очень локальная задача

Ну если использование огромного количества стандартных библиотек .Net и расширения за счет написания своих библиотек и практически замена COM это локальная задача, то что называется глобальной?
16. Сергей Смирнов (Serginio) 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,ТекущаяДата()));

...Показать Скрыть




Это удобно при работе с различными парсерами
17. Сергей Поляков (PolSerg) 08.07.16 09:28
(7) Serginio, Причем здесь импортозамещение, Linux интересен прежде всего тем, что не кишит всякой заразой как винда, поэтому и тренд во многих компаниях, включая ту в которой работаю я, как бонус свободный софт, как правило, бесплатен.
18. Сергей Смирнов (Serginio) 08.07.16 10:08
(17) Если ты прочитал 7 то это не мой термин. Но, что скажешь по поводу расширения функционала 1С на Linux за счет использования классов .Net?
19. Сергей Смирнов (Serginio) 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) 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) 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) 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,"ХаХа"));
...Показать Скрыть
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа