📜 ⬆️ ⬇️

Cross-platform use of .Net classes in 1C through Native VK. Or replacing COM with Linux II

This is a continuation of the articles:

» Development → Cross-platform use of .Net classes from unmanaged code. Or analogue IDispatch on Linux
» Development → Cross-platform use of .Net classes in 1C through Native VK. Or replacing COM with Linux

Since then, added support for methods with default parameters, calling extension methods, inferring types for generic methods, supporting objects implementing IDynamicMetaObjectProvider (ExpandoObject, DynamicObject), adding synonyms to type members and asynchronous programming on 1C!

At one time I wrote an article .Net in 1C. On the example of using HTTPClient, AngleSharp. Convenient parsing of sites using the AngleSharp library, including authorization ala JQuery using CSS selectors. Dynamic compilation
')
In which there was an example of using extension methods, generic methods, default parameters. As a result, the code using IReflect was very far from real in C #. In the new version I tried to bring the code to 1C as close as possible to the original.

Let's look at an example in 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)); 

Here is its analogue on 1C:

 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); 

Let me draw attention to a few points. Design:

 document.QuerySelector<IHtmlAnchorElement>(rowSelector); 

On 1C it looks like this:

 HtmlAnchorElement=((document.in(IHtmlAnchorElement.())).QuerySelector(rowSelector)); 

I used the reserved word in to create a descendant of DynamicObject, in which the object and generic arguments are saved, and then through TryInvokeMember we get the method name and parameters and find the right method and execute it.

So far, for generics, I have not implemented methods with default parameters and array parameters.

For generics, the types for the following constructions are displayed:

 public K 3<K>(IList<K> param1, int param2, K param3) 

1C example

 List=("System.Collections.Generic.List`1[System.String]"); (.3(List.(),3,"3")); 

The type is inferred from the List, resulting in an Ilist and comparing the result with a type of 3 parameters.

I was often reproached for using .NET assemblies in 1C 7.xb 8.x. Creating an external component.

1. No cross-platform
2. No Russian synonyms.

Well, with MS help, and made a cross-platform component. And made the ability to add synonyms to the type.

 AngleSharp=(.("AngleSharp")); Assembly=(AngleSharp.GetType()); .(Assembly.(),"","GetType"); //       AngleSharp_Configuration=(AngleSharp.("AngleSharp.Configuration")); //     GetType HtmlParser=(AngleSharp.GetType("AngleSharp.Parser.Html.HtmlParser")); 

Synonyms can also be used from extensions. For example:

 public static class  { public static string (this  ,string Str) { return .()+" "+ Str; } } 

Now you can call:

  //         //(, "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")); 

You can also call extensions for generic methods. Including with a withdrawal on restriction.

ApiExtensions extension method:

 public static Task<IDocument> ApiExtensions.NavigateAsync<TElement>(this TElement element) where TElement : IUrlUtilities, IElement; 

The type of this TElement on the IElement constraint is displayed.

 doc=((HtmlAnchorElement.NavigateAsync()).Result); 

I have not yet found a way to view all loaded assemblies. Therefore, the search for extensions is being done in the assembly where the type is located with the called method. I hope the release will come out in the fall with great potential.

Also added a shorter record of getting the interface.

Instead

 =(.(.(),"IEnumerable")); 


Can be used as

 =(.as("IEnumerable")); =(.GetEnumerator()); //       IEnumerator =(.as("IEnumerator")); 


Examples and sources can be downloaded here.
In the next article, Asynchronous Programming in 1C via .Net Native VK I will talk about asynchronous programming in 1C.

Source: https://habr.com/ru/post/307188/


All Articles