Багатоплатформовий використання класів .Net в 1С через Native ВК. Або заміна COM на Linux II

Це продовження статей:

» Розробка → Багатоплатформовий використання класів .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С.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.