Question:
There is an idea to have access from TypeScript to methods and properties of .Net classes.
I have experience calling methods of .Net objects from native https://habrahabr.ru/users/serginio1/topics/
And in particular Cross-platform use of .Net classes from unmanaged code. Or analogue of IDispatch on Linux
There is an idea to call through Native Client Messaging System
There we have JavaScript and native interaction through messages
In JavaScript, we can subscribe to events
function handleMessage(message) {
// In the example, we simply log the data that's received in the message.
var logEl = document.getElementById('log');
logEl.textContent += message.data;
}
And send messages
var dictionary = {
key:guid,
MethodName: name,
param_array: args
}
nacl_module.postMessage(dictionary);
On the native side
You can receive messages
virtual void HandleMessage(const pp::Var& var) {
if (var.is_dictionary()) {
pp::VarDictionary dictionary(var);
// Use the dictionary
pp::VarArray keys = dictionary.GetKeys();
// ...
} else {
// ...
}
}
So send it
pp::VarDictionary dictionary;
dictionary.Set(pp::Var("command"), pp::Var(next_command));
dictionary.Set(pp::Var("param_int"), pp::Var(123));
pp::VarArray an_array;
an_array.Set(0, pp::Var("string0"));
an_array.Set(1, pp::Var("string1"))
dictionary.Set(pp::Var("param_array"), an_array);
PostMessage(dictionary);
All this can be done through Proxy
class NetWrapper{
public currentCount: any;
public static dictionary = {};
public proxy: any;
public static wm = new WeakMap(); // Слабые ссылки на объекты
public static refArray = new Array<int>(); // ссылки на .Net объекты
constructor(private netRef:int) { this.SetProxy(); }
private GetPromise(name: PropertyKey,args)
{
let key = Guid.newGuid();
let promise = new Promise((resolve, reject) => {
let item = new Item(resolve, args, name);
this.dictionary[key] = item;
var dictionary = {
netRef:netRef,
key:key,
MethodName: name,
param_array: args
}
nacl_module.postMessage(dictionary);
});
return promise;
}
private SetProxy(): void {
let self=this;
this.proxy = new Proxy({}, {
get: function(rcvr: any, name: PropertyKey)
{
// Проблемы с определением, что свойство возвращает ссылку на метод
// поэтому будем вызвать все как методы
// if (этоСвойство)
// return self.GetPromise(name, []);
return (...args) => {
return self.GetPromise(name,args)
};
}
});
}
// Пример вызова метода .Net
function handleMessage(message) {
// In the example, we simply log the data that's received in the message.
let data=message.data;
let result=data.result;
let item = <Item>this.dictionary[data.key];
delete this.dictionary[key];
if (data.resultIsObject)
{
let ref=<int>result;
result=new NetWrapper(ref);
refArray.push(ref);
wm.set(result,ref);
}
item.resolve(result);
}
Since there are no finalizers in JavaScript, we can use WeakMap
That is, it would be possible to unload the values from wm and compare them with the current refArray. If there are no links in WeakMap, then you can release links on the .Net side
But it seems like
Because references are weak, WeakMap's keys are not enumerable (that is, there is no method that returns a list of keys). Otherwise the list would depend on the garbage collection state, introducing indeterminism. If you want to have a list of keys, you must maintain it yourself.
Usage is
let HttpClient=await NetWrap.GetType("System.Net.Http.HttpClient","System.Net.Http.dll");
let HttpClientHandler = await NetWrap.GetType("System.Net.Http.HttpClientHandler","System.Net.Http.dll");
let client=await NetWrap.new(HttpClient);
let responst= await (await client.GetStringAsync("https://msdn.microsoft.com/ru-ru/library/hh551745(v=vs.118).aspx")).Result();
//Result вызываем как функцию
It is possible for asynchronous result methods inside Net to be made asynchronous
I will be glad to any advice. And maybe no one needs it and you shouldn’t write to the table at all?
True, I found a link to the finalizer feature https://www.npmjs.com/package/finalize
var finalize = require('finalize');
var obj = { x: 1337 };
finalize(obj, function () {
console.log(this.x); // this will print '1337'
});
global.gc();
// nothing will happen, var obj above holds obj alive
obj = null;
global.gc();
// the previous line should trigger the callback above
In addition, cef / JavaScriptIntegration was given to me for integration
You can do without the asynchrony of calling ordinary methods.
At the same time, you can register various handlers for asynchronous methods, for events
As a result, you can call asynchronous methods, for example, by adding the async keyword, and for properties, you can use @ at the beginning of the property
let url= "https://msdn.microsoft.com/ru-ru/library/hh551745(v=vs.118).aspx");
let response= await client.async.GetStringAsync(url);
let response= client.GetStringAsync(url).@Result;
Answer:
Made and works on Angular 2 and TypeScript
let Net = NetObject.NetWrapper;
let del = NetObject.FlagDeleteObject;
//let SB = Net.Новый("System.Text.StringBuilder");
let StringBuilder = Net.Тип("System.Text.StringBuilder");
let SB = new StringBuilder();
this.AddComment("SB", SB);
var res = SB.Append("Первая строка");
res(del);
var ToStr = SB.ToString();
this.AddComment("Tostring=", ToStr);
SB.Capacity=40;
res = SB._Capacity;
this.AddComment("_Capacity=", res);
SB(del);
let Тестовый = Net.Тип("TestDllForCoreClr.Тестовый", "TestDllForCoreClr");
var TO = new Тестовый("Свойство из Конструктора");
var resAsync = await TO.async.GetStringAsync();
this.ResultExecute.push(new ResTest("GetStringAsync", resAsync));
res = TO.ДженерикМетод(1, 2, 5);
this.AddComment("ДженерикМетод с выводом типов ", res);
let Int32 = Net.GetType("System.Int32");
res = TO.ДженерикМетод([Int32, Int32], 1, 2, 5);
this.AddComment("ДженерикМетод с аргeментами типов ", res);
var Dictionary2 = Net.GetType("System.Collections.Generic.Dictionary`2", "System.Collections");
var DyctionaryIS = Net.GetGenericType(Dictionary2, "System.Int32", "System.String");
var D = new DyctionaryIS();
res = TO.ДженерикМетод2(D, 99, "Hello");
this.AddComment("ДженерикМетод2 с выводом типов ", res);
res = TO.ДженерикМетод2([Int32, "System.String"],D, 99, "Hello");
this.AddComment("ДженерикМетод2 с аргументами ", res);
var task = TO.GetStringAsync();
res = await Net.async.ReturnParam(task);
this.AddComment("выполнение полученной задачи асинхронно ", res);
var array = Net.GetNetArray(1, "Привет", 4.4);
for (let item of array)
this.AddComment("Элемент ", item);
var EO = TO.ПолучитьExpandoObject();
this.AddComment("Свойство ExpandoObject Имя ",EO._Имя);
this.AddComment("Свойство ExpandoObject Число ", EO._Число);
var делегат = EO._ВСтроку;
this.AddComment("Результат вызова делегата Встроку ", делегат());
this.AddComment("Результат вызова как Метода ", EO.ВСтроку());
NetObject.DeleteNetObjets(Int32, task, D, DyctionaryIS, Dictionary2, TO, Тестовый, StringBuilder, array, EO, делегат);
this.AddComment("Количество элементов в хранилище ", Net.КоличествоЭлементовВХранилище());
this.AddComment("Первый удаленный ", Net.FirstDeleted());
The difference from C# is To get the property you need to add "_"
res = SB._Capacity;
To call an asynchronous method, add the async keyword
var resAsync = await TO.async.GetStringAsync();
To call a generic method, if it is impossible to infer types by parameters, then specify the arguments in an array
res = TO.ДженерикМетод2([Int32, "System.String"],D, 99, "Hello");
Support for events and passing JS objects will be added later. I will be glad to any suggestions and criticism. What are the best examples for an article?
As a result, I posted an article with examples of CEF, ES6, Angular 2, TypeScript using .Net Core classes to extend capabilities
And more CEF, Angular 2 using .Net Core class events
And more CEF, ES6, Angular 2, WebPack 2 .Net Core desktop app without backend