Это продолжение статей:
» Разработка > Кроссплатформенное использование классов .Net из неуправляемого кода. Или аналог IDispatch на Linux
» Разработка > Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux
С того времени добавил поддержку методов с параметрами по умолчанию, вызов методов расширений, вывод типов для дженерик методов, поддержка объектов реализующих IDynamicMetaObjectProvider (ExpandoObject,DynamicObject), добавление синонимов к членам типа и асинхронное программирование на 1С!
В свое время написал статью .Net в 1С. На примере использования HTTPClient,AngleSharp. Удобный парсинг сайтов с помощью библиотеки AngleSharp, в том числе с авторизацией аля JQuery с использованием CSS селекторов. Динамическая компиляция
В котором был пример использования методов расширения, дженерик методов, параметров по умолчанию. И в итоге код с использованием IReflect был очень далек от реального на C#. В новой версии я попытался максимально приблизить код на 1С к оригиналу.
Разберем пример на C#
Вот его аналог на 1С:
Обращу внимание на несколько моментов. Конструкция:
На 1С выглядит так:
Я использовал зарезервированное слово in Для создания потомка DynamicObject, в котором сохраняются объект и дженерик аргументы, а затем через TryInvokeMember получаем имя метода и параметры и находим нужный метод и выполняем.
Пока для дженериков не реализовал методы с дефолтными параметрами и параметрами массивами.
Для дженериков выводится типы для таких конструкций:
Пример на 1С
Тип выводится из List приводя к Ilist и сравнивая результат с типом 3 параметра.
Меня очень часто упрекали за Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент.
1. Нет кроссплатформенности
2. Нет рускоязычных синонимов.
Ну с кроссплатформенностью подсобил MS, и сделал кроссплатформенную компоненту. И сделал возможность добавлять синонимы к типу.
Синонимы можно использовать и из расширений. Например:
Теперь можно вызвать:
Так же можно вызывать расширения и для дженерик методов. В том числе с выводом по ограничению.
Метод расширения ApiExtensions:
Выводится тип this TElement по ограничению IElement
Пока не нашел способа просмотреть все загруженные сборки. Поэтому поиск расширений пока ведется в сборке где находится тип с вызываемым методом. Надеюсь осенью выйдет релиз с большими возможностями.
Кроме того добавил более краткую запись получения интерфейса
Вместо
Можно использовать as
Примеры и исходники можно скачать Здесь
В следующей статье Асинхронное программирование в 1С через .Net Native ВК расскажу про асинхронное программирование в 1С.
» Разработка > Кроссплатформенное использование классов .Net из неуправляемого кода. Или аналог IDispatch на Linux
» Разработка > Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux
С того времени добавил поддержку методов с параметрами по умолчанию, вызов методов расширений, вывод типов для дженерик методов, поддержка объектов реализующих IDynamicMetaObjectProvider (ExpandoObject,DynamicObject), добавление синонимов к членам типа и асинхронное программирование на 1С!
В свое время написал статью .Net в 1С. На примере использования HTTPClient,AngleSharp. Удобный парсинг сайтов с помощью библиотеки AngleSharp, в том числе с авторизацией аля JQuery с использованием CSS селекторов. Динамическая компиляция
В котором был пример использования методов расширения, дженерик методов, параметров по умолчанию. И в итоге код с использованием IReflect был очень далек от реального на C#. В новой версии я попытался максимально приблизить код на 1С к оригиналу.
Разберем пример на C#
var config = Configuration.Default.WithDefaultLoader().WithCookies();
// Устанавливаем адрес страницы сайта
var address = "https://en.wikipedia.org/wiki/List_of_The_Big_Bang_Theory_episodes";
// загружаем страницу и разбираем её
var document = BrowsingContext.New(config).OpenAsync(address).Result;
// найдем <a href="/wiki/The_Big_Bang_Theory" title="The Big Bang Theory">The Big Bang Theory</a>
var rowSelector = "a[title='The Big Bang Theory']";
var HtmlAnchorElement = document.QuerySelector<IHtmlAnchorElement>(rowSelector);
rowSelector="form#searchform";
var FormElement = doc.<IHtmlFormElement>QuerySelector(rowSelector));
Вот его аналог на 1С:
СборкаAngleSharp=ъ(Врап.Сборка("AngleSharp"));
Assembly=ъ(СборкаAngleSharp.GetType());
Врап.ДобавитьСиноним(Assembly.ПолучитьСсылку(),"Тип","GetType");
// Теперь мы можем использовать синоним Тип
AngleSharp_Configuration=ъ(СборкаAngleSharp.Тип("AngleSharp.Configuration"));
// Или вызвать реальный метод GetType
HtmlParser=ъ(СборкаAngleSharp.GetType("AngleSharp.Parser.Html.HtmlParser"));
//Получим типы
BrowsingContext = ъ(СборкаAngleSharp.Тип("AngleSharp.BrowsingContext"));
Configuration=ъ(СборкаAngleSharp.Тип("AngleSharp.Configuration"));
// Методы рсширения ConfigurationExtensions
// public static IConfiguration WithDefaultLoader(this IConfiguration configuration, Action<LoaderService> setup = null, IEnumerable<IRequester> requesters = null);
// public static IConfiguration WithCookies(this IConfiguration configuration);
config = ъ(ъ(ъ(Configuration.Default).WithDefaultLoader()).WithCookies());
address = "https://en.wikipedia.org/wiki/List_of_The_Big_Bang_Theory_episodes";
context = ъ(BrowsingContext.New(config.ПолучитьСсылку()));
// Загрузим начальную страницу
// Метод расширения BrowsingContextExtensions
//public static Task<IDocument> OpenAsync(this IBrowsingContext context, string address);
document = ъ(ъ(context.OpenAsync(address)).Result);
rowSelector = "a[title='The Big Bang Theory']";
// Метод расширения ApiExtensions
//public static TElement QuerySelector<TElement>(this IParentNode parent, string selectors) where TElement : class, IElement;
HtmlAnchorElement=ъ(ъ(document.in(IHtmlAnchorElement.ПолучитьСсылку())).QuerySelector(rowSelector));
//Метод расширения ApiExtensions
//public static Task<IDocument> ApiExtensions.NavigateAsync<TElement>(this TElement element) where TElement : IUrlUtilities, IElement;
//Вывод типа this TElement по ограничению IElement
doc=ъ(ъ(HtmlAnchorElement.NavigateAsync()).Result);
rowSelector="form#searchform";
FormElement = ъ(ъ(doc.in(IHtmlFormElement.ПолучитьСсылку())).QuerySelector(rowSelector));
Сообщить("OuterHtml="+FormElement.OuterHtml);
Обращу внимание на несколько моментов. Конструкция:
document.QuerySelector<IHtmlAnchorElement>(rowSelector);
На 1С выглядит так:
HtmlAnchorElement=ъ(ъ(document.in(IHtmlAnchorElement.ПолучитьСсылку())).QuerySelector(rowSelector));
Я использовал зарезервированное слово in Для создания потомка DynamicObject, в котором сохраняются объект и дженерик аргументы, а затем через TryInvokeMember получаем имя метода и параметры и находим нужный метод и выполняем.
Пока для дженериков не реализовал методы с дефолтными параметрами и параметрами массивами.
Для дженериков выводится типы для таких конструкций:
public K ДженерикМетод3<K>(IList<K> param1, int param2, K param3)
Пример на 1С
List=ъНовый("System.Collections.Generic.List`1[System.String]");
Сообщить(Тест.ДженерикМетод3(List.ПолучитьСсылку(),3,"Привет3"));
Тип выводится из List приводя к Ilist и сравнивая результат с типом 3 параметра.
Меня очень часто упрекали за Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент.
1. Нет кроссплатформенности
2. Нет рускоязычных синонимов.
Ну с кроссплатформенностью подсобил MS, и сделал кроссплатформенную компоненту. И сделал возможность добавлять синонимы к типу.
СборкаAngleSharp=ъ(Врап.Сборка("AngleSharp"));
Assembly=ъ(СборкаAngleSharp.GetType());
Врап.ДобавитьСиноним(Assembly.ПолучитьСсылку(),"Тип","GetType");
// Теперь мы можем использовать синоним Тип
AngleSharp_Configuration=ъ(СборкаAngleSharp.Тип("AngleSharp.Configuration"));
// Или вызвать реальный метод GetType
HtmlParser=ъ(СборкаAngleSharp.GetType("AngleSharp.Parser.Html.HtmlParser"));
Синонимы можно использовать и из расширений. Например:
public static class РасширенияДляТестовый
{
public static string ПолучитьСтрокуИзРасширенияСпарам(this Тестовый тест,string Str)
{
return тест.ПолучитьСтроку()+" "+ Str;
}
}
Теперь можно вызвать:
// Ищем сборку по путям переданным при создании компоненты
//ПодключитьВнешнююКомпоненту(ИмяФайла, "NetObjectToNative",ТипВнешнейКомпоненты.Native);
// Врап = Новый("AddIn.NetObjectToNative.LoaderCLR");
// Врап.СоздатьОбертку(CoreClrDir,ДиректорияNetObjectToNative,"");
// Где
// CoreClrDir Это директория где лежат основные библиотеки .Net и в частности coreclr
// ДиректорияNetObjectToNative директория где лежит эта сборка
// на данный момент все пользовательские сборки нужно сохранять рядом с ней
//Пример использования
//СборкаHttpClient=ъ(Врап.Сборка("System.Net.Http",истина));
//HttpClient=ъ(СборкаHttpClient.GetType("System.Net.Http.HttpClient"));
// Можно опускать разрешение. По умолчанию Dll
РасширенияДляТестовый=ъ(СборкаТестовый.Тип("TestDllForCoreClr.РасширенияДляТестовый"));
Врап.ДобавитьСиноним(РасширенияДляТестовый.ПолучитьСсылку(),"GetStringFromExtensionWithParams","ПолучитьСтрокуИзРасширенияСпарам");
// Вызовем по оригигальному названию
Сообщить(Тест.ПолучитьСтрокуИзРасширенияСпарам("Привет"));
// Вызовем по синониму
Сообщить(Тест.GetStringFromExtensionWithParams("Привет из GetStringFromExtensionWithParams"));
Так же можно вызывать расширения и для дженерик методов. В том числе с выводом по ограничению.
Метод расширения ApiExtensions:
public static Task<IDocument> ApiExtensions.NavigateAsync<TElement>(this TElement element) where TElement : IUrlUtilities, IElement;
Выводится тип this TElement по ограничению IElement
doc=ъ(ъ(HtmlAnchorElement.NavigateAsync()).Result);
Пока не нашел способа просмотреть все загруженные сборки. Поэтому поиск расширений пока ведется в сборке где находится тип с вызываемым методом. Надеюсь осенью выйдет релиз с большими возможностями.
Кроме того добавил более краткую запись получения интерфейса
Вместо
Перечислимый=ъ(Врап.ПолучитьИнтерфейс(Объект.ПолучитьСсылку(),"IEnumerable"));
Можно использовать as
Перечислимый=ъ(Объект.as("IEnumerable"));
Перечислитель=ъ(Перечислимый.GetEnumerator());
// На всякий случай приведем к Интерфейсу IEnumerator
Перечислитель=ъ(Перечислитель.as("IEnumerator"));
Примеры и исходники можно скачать Здесь
В следующей статье Асинхронное программирование в 1С через .Net Native ВК расскажу про асинхронное программирование в 1С.
Поделиться с друзьями
Комментарии (17)
Daniro_San
10.08.2016 02:33НачатьКомментарий ПечатьТекст РусскийЯзыкСмешатьСАнглийскийЯзык Аз ЕсмьЗло КонецКомментарий
Serginio1
10.08.2016 10:02Вы что с гор спустились. Не разу не видели кириллицу? Есть нормально.
Еще раз читайте про синонимы. Я их не зря ввел.AntonL
10.08.2016 13:52Синонимы надо на русские названия делать(заменяя английскими) :)
Serginio1
10.08.2016 14:24Там как раз есть пример.
РасширенияДляТестовый=ъ(СборкаТестовый.Тип("TestDllForCoreClr.РасширенияДляТестовый")); Врап.ДобавитьСиноним(РасширенияДляТестовый.ПолучитьСсылку(),"GetStringFromExtensionWithParams","ПолучитьСтрокуИзРасширенияСпарам"); // Вызовем по оригигальному названию Сообщить(Тест.ПолучитьСтрокуИзРасширенияСпарам("Привет")); // Вызовем по синониму Сообщить(Тест.GetStringFromExtensionWithParams("Привет из GetStringFromExtensionWithParams"));
То есть все в твоих руках. Хочешь по англицки то пиши по англицки, хочешь на русском пиши по русском.
На вкус и цвет товарищей нет.
AntonL
Жесть
doc=ъ(ъ(HtmlAnchorElement.NavigateAsync()).Result);
Перечислимый=ъ(Врап.ПолучитьИнтерфейс(Объект.ПолучитьСсылку(),"IEnumerable"));
Serginio1
Я в предыдущей статье писал, что в Native Api можно использовать только простые типы и строкию
В новой версии можно использовать as
cleaner_it
Я думаю, речь о другом, а именно о «Ъ».
Предыдущую статью не читал, но как разработчик с 16 летним стажем, из них 10 лет на 1С — я в недоумении от этой конструкции. Названия любых методов, функций, переменных должны быть говорящими.
Serginio1
При этом код будет состоять из сплошных СоздатиьОбъектИзСсылки?
cleaner_it
Даже в этом случае код будет выглядеть лучше. Любой разработчик, который будет работать после вас — скажет большое спасибо. Или, вернее, ничего не скажет — это просто будет хороший код, который не цепляет несуразностями.
Код не только должен работать и работать хорошо. Код должен быть читаемым и понятным. Помните программу в С++ 3.11, код которой напоминал набор символов, но при этом выдавал осмысленный результат в виде текста? Я даже сейчас не имею желания разобраться в ней.
PS:
Можно ведь использовать и сокращенный синоним — cog (CreateObjectFromGuid).
Serginio1
Я не вижу огромной разницы между $ ъ cog. Они не несут никакой смысловой нагрузки. А вот код на 1С максимально приближен к коду на C#
И ъ будет встречаться на каждом шагу. Поэтому вэб программисты испльзуя JQuery используют $ а не метод JQuery
Никто не запрещает тебе использовать вместо ъ cog. Это дело вкуса.
Serginio1
Из-за того, что в Native Api нельзя передавать ту же ВК приходится делать такие конструкции
Если же использовать осмысленное СоздатьОбъектПоСсылке то это превращается
На самом деле я просто позаимствовал подход из JQuery где наравне с jQuery используется $. И никого это не раздражает
cleaner_it
Мне кажется, этот код вообще нужно распарсить. Компилятору всё равно, а вам удобнее.
1) Было
config = ъ(ъ(ъ(Configuration.Default).WithDefaultLoader()).WithCookies());
2) Стало
Loader = СоздатьОбъектПоСсылке(Configuration.Default).WithDefaultLoader())
Cookies = СоздатьОбъектПоСсылке(Loader.WithCookies()
Config = СоздатьОбъектПоСсылке(Cookies);
PS;
Почему ъ — это СоздатьОбъектПоСсылке? Вот здесь я не вижу ссылки, я вижу тип значения: Assembly=ъ(СборкаAngleSharp.GetType());
Где почитать про момент ввода «ъ» и программный код «ъ»?
Serginio1
Я в предыдущих статьях писал, что в Native Api нельзя возвращать и передавать объекты. Поэтому передается специально закодированная строка, что бы по ней определить, что это ссылка на объект при передаче в параметрах и извлечь из неё индекс в массиве хранилища объекта. Можно посмотреть код по ссылке.
Serginio1
ъ это из других статей
Serginio1
Я в статье дал ссылку на статью где используется COM через IReflect. Там можно получать и передавать объекты, но нет возможности использовать дженерики напрямую.
Net в 1С. На примере использования HTTPClient,AngleSharp. Удобный парсинг сайтов с помощью библиотеки AngleSharp, в том числе с авторизацией аля JQuery с использованием CSS селекторов. Динамическая компиляция
Приведу код который решает ту же задачу, но он менее удобный чем с ъ
В C# есть удобный сахар в виде расширений. Например, код
//На самом деле представляет собой
//
Кроме того, используются дженерик функции. Я покажу, как с этим бороться.
Но, к сожалению, красивый код на C# превращается в монстра на 1С. Но зато есть примеры, как с этим бороться
Serginio1
В шапке статьи есть ссылка на предыдущюю статью Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux
Которая в свою очередь ссылается на Кроссплатформенное использование классов .Net из неуправляемого кода. Или аналог IDispatch на Linux
И там подробно описано, что как и почему.
Так как из Native ВК возвращается закодированная строка например ёЁ<Ьъ>№_%)Э?&2
//Физически это строка ёЁ<Ьъ>№_%)Э?&2 содержащее 12 символов для отделения их от других строк
//и индекс в спике исполуемых объектов на стороне .Net
То есть СборкаAngleSharp.GetType() вернет не объект а строку.
cleaner_it
Мне нужно немного времени, чтобы разобраться — заинтересовало