CEF、Angular 2 .Net Coreクラスイベントの使用

これは、 .Net Coreクラスを使用して機能を拡張するCEF、ES6、Angular 2、TypeScriptのフォローアップです。



予想通り、彼女はあまり注目されませんでした。 しかし、私の仕事に興味を持っている人々に感謝します。 研究を続けるインセンティブを与えてくれるのはあなたです。



CEFについて少し説明します。



これは、C ++ネイティブコードの使用による無制限の拡張機能を備えたクロスプラットフォームブラウザー(Google Chromeで使用されるコアを使用)であり、UIを備えた本格的なクロスプラットフォームデスクトップアプリケーションを作成できます。



さらに、 Chrome 57はWebサイトのCおよびC ++言語のサポートを提供します。



今日は、Angular 2のオブジェクト.Net Coreクラスのイベントの使用方法を示します。

多くの人は、.Netクラスを使用する代わりにHTTPサービスを使用できると主張する最初の記事を読みました。



しかし、イベントでは、取引機器を使用した本格的なデスクトップアプリケーション、さまざまなプロトコルを使用したデータ交換、インスタントメッセンジャーなどを使用できます。



例として、イベントを持つクラスを取り上げます。



public class EventTest { public event Action<string, int> EventWithTwoParameter; public event Action<string> EventWithOneParameter; public event Action EventWithOutParameter; public bool IsRun = false; public void Test() { EventWithTwoParameter?.Invoke(DateTime.Now.ToString(), 1); EventWithOneParameter?.Invoke(DateTime.UtcNow.ToString()); EventWithOutParameter?.Invoke(); } public async void Run() { if (IsRun) return; IsRun = true; while (IsRun) { await Task.Delay(2000); Test(); } } }
      
      





これで、Angular 2でこのクラスを使用できます。



 export class TestEventComponent { EventsRes: EventRes[] = []; WOWE: WrapperObjectWithEvents; test: any; EventTest: any; constructor(private ngZone: NgZone) { let Net = NetObject.NetWrapper; //    . this.EventTest = Net.GetType("TestDllForCoreClr.EventTest", "TestDllForCoreClr"); //   this.test = new this.EventTest(); //    ,     //    . this.CreateWrapperForEvents(this.test); } //        //   . //  value:  //   // arg1:System.String // arg2:System.Int32 public EventWithTwoParameter(value: any) { this.AddComment("EventWithTwoParameter", NetObject.NetWrapper.toString(value)); value(NetObject.FlagDeleteObject); } //  value:System.String public EventWithOneParameter(value: any) { this.AddComment("EventWithOneParameter ",NetObject.NetWrapper.toString(value)); } public EventWithOutParameter(value: any) { this.AddComment("EventWithOutParameter", NetObject.NetWrapper.toString(value)); } CreateWrapperForEvents(obj: any): void { let wrapForEvents = NetObject.GetWrapperForObjectWithEvents(obj, this.ngZone); wrapForEvents.AddEventHandler("EventWithTwoParameter", this.EventWithTwoParameter.bind(this)); wrapForEvents.AddEventHandler("EventWithOneParameter", this.EventWithOneParameter.bind(this)); wrapForEvents.AddEventHandler("EventWithOutParameter", this.EventWithOutParameter.bind(this)); //   wrapForEvents   this.WOWE = wrapForEvents; }
      
      





コンポーネントが破壊された場合、.Net側のリンクをクリアすることを忘れないでください。



 ngOnDestroy() { NetObject.DeleteNetObjets(this.EventTest, this.test); this.WOWE.Close(); alert("    .Net ="+Net.CountItemsInStore()); }
      
      





イベントの購読を解除するには、3つの方法があります。



// Subjectオブジェクトのsubscribeメソッドの結果を取得します。



 this.AddEventHandlerResult= wrapForEvents.AddEventHandler("EventWithTwoParameter", this.EventWithTwoParameter.bind(this));
      
      





それを使用して、イベントから説明します。



 this.AddEventHandlerResult.unsubscribe();
      
      





ただし、.NetからのイベントはJS側で処理されます。



次の2つのオプションは、それ自体を表しています。



 this.WOWE.RemoveEventHandler("EventWithTwoParameter"); this.WOWE.RemoveAllEventHandler();
      
      





次のように、イベントを説明するためのTSモジュールのテキストを取得できます。



 let DescribeMethodsTS= Net.GetType("NetObjectToNative.DescribeMethodsTS", "NetObjectToNative"); this.CodeModule = DescribeMethodsTS.GetCodeModuleTS(this.EventTest);
      
      





NgZoneが必要な理由については、こちらをご覧ください。 ゾーンとは何ですか?



それでは、インとアウトに移りましょう。 動的イベントコンパイルは、イベントラッパーを取得するために使用されます。 このプロセスは、 1C、.Net Coreで詳細に説明されています。 1Cのオブジェクトの.Netイベントを受信するためのラッパークラスの動的コンパイル



CEFにはいくつかの変更があります。



イベントラッパーコード
 //            CEF public class ClassForEventCEF { EventInfo EI; public string EventKey; public IntPtr CppHandler; public object WrapperForEvent; public ClassForEventCEF(object WrapperForEvent, string EventKey, EventInfo EI, IntPtr CppHandler) { this.EventKey = EventKey; this.EI = EI; this.CppHandler = CppHandler; this.WrapperForEvent = WrapperForEvent; //    EI.AddEventHandler(WrapperForEvent, new System.Action<object>(CallEvent)); } public void CallEvent(object value) { IntPtr ResIntPtr = AutoWrap.AllocMem(48); var EventKeyPtr = WorkWithVariant.WriteStringInIntPtr(EventKey); WorkWithVariant.SetObjectInIntPtr(AutoWrap.WrapObject(value), ResIntPtr); //      CEF //        AutoWrap.EventCall(CppHandler, EventKeyPtr, ResIntPtr); } public void RemoveEventHandler() { EI.RemoveEventHandler(WrapperForEvent, new System.Action<object>(CallEvent)); } }
      
      





このクラスは動的に生成されます:



 public class WrapperForEventTestDllForCoreClr_EventTest { public IntPtr CppHandler; public TestDllForCoreClr.EventTest Target; Dictionary<string, ClassForEventCEF> EventStoage=new Dictionary<string, ClassForEventCEF>(); public event Action<object> EventWithTwoParameter; public event Action<object> EventWithOneParameter; public event Action<object> EventWithOutParameter; public WrapperForEventTestDllForCoreClr_EventTest(IntPtr CppHandler, TestDllForCoreClr.EventTest Target) { this.CppHandler = CppHandler; this.Target = Target; Target.EventWithTwoParameter += (arg1,arg2) => { if (EventWithTwoParameter!=null) { var EventWithTwoParameterObject = new {arg1=arg1,arg2=arg2}; EventWithTwoParameter(EventWithTwoParameterObject); } }; Target.EventWithOneParameter += (obj) => { if (EventWithOneParameter!=null) EventWithOneParameter(obj); }; Target.EventWithOutParameter += () => { if (EventWithOutParameter!=null) EventWithOutParameter(null); }; } public void AddEventHandler(string EventKey, string EventName) { EventInfo ei = GetType().GetEvent(EventName); var forEvent = new ClassForEventCEF(this,EventKey, ei,CppHandler); EventStoage.Add(EventKey, forEvent); } public void RemoveEventHandler(string EventKey) { ClassForEventCEF cfe = null; if (EventStoage.TryGetValue(EventKey,out cfe)) { EventStoage.Remove(EventKey); cfe.RemoveEventHandler(); } } public void RemoveAllEventHandler() { foreach( var cfe in EventStoage.Values) cfe.RemoveEventHandler(); EventStoage.Clear(); } public static object CreateObject(IntPtr Self, TestDllForCoreClr.EventTest Target) { return new WrapperForEventTestDllForCoreClr_EventTest(Self, Target); } } return new Func<IntPtr, TestDllForCoreClr.EventTest, object>(WrapperForEventTestDllForCoreClr_EventTest.CreateObject);
      
      







JS側では、イベントは次のように処理されます。



TS側のイベントラッパーコード
 class EventEmitter{ public subject = new Subject<any>(); constructor(private ngZone: NgZone) { // this.data = Observable.create((observer: any) => this.dataObserver = <Observer<any>>observer); } public subscribe(EventHandler: (value: any) => void) { return this.subject.subscribe({ next: (v) => this.ngZone.run(()=> EventHandler(v)) }); } public emit(value: any) { this.subject.next(value); } public Complete() { this.subject.complete(); } } class EventItem { constructor(public EventKey: string, public Event:EventEmitter){} } //EventEmitter export class WrapperObjectWithEvents { //     EventKey  EventEmitter EventsList = new Map<string, EventItem>(); //  EventKey  EventEmitter EventEmittersList = new Map<string, EventEmitter>(); constructor(private NetTarget: any, private ngZone: NgZone) { }; //       .Net public RaiseEvent(EventKey: string, value: any) { //   ,    if (this.EventEmittersList.has(EventKey)) { let Event = this.EventEmittersList.get(EventKey); Event.emit(value); } } public AddEventHandler(EventName: string, EventHandler: (value: any) => void): any { let ei: EventItem; let isFirst = false; if (!this.EventsList.has(EventName)) { let EventKey = window.CallNetMethod(0, "GetUniqueString"); let Event = new EventEmitter(this.ngZone); ei = new EventItem(EventKey, Event); this.EventsList.set(EventName, ei); this.EventEmittersList.set(EventKey, Event); NetObject.EventCallers.set(EventKey, this.RaiseEvent.bind(this)); isFirst = true; } else ei = this.EventsList.get(EventName); // let res = ei.Event.subscribe(this.ngZone.run(() =>EventHandler)); let res = ei.Event.subscribe((value: any) => { EventHandler(value) }); if (isFirst) this.NetTarget.AddEventHandler(ei.EventKey, EventName); return res; } public RemoveEventHandler(EventName: string) { if (this.EventsList.has(EventName)) { let ei = this.EventsList.get(EventName); let EventKey = ei.EventKey this.NetTarget.RemoveEventHandler(EventKey); NetObject.EventCallers.delete(EventKey); this.EventEmittersList.delete(EventKey); this.EventsList.delete(EventName); ei.Event.Complete(); } } public RemoveAllEventHandler() { this.NetTarget.RemoveAllEventHandler(); for (let ei of this.EventsList.values()) { { NetObject.EventCallers.delete(ei.EventKey); ei.Event.Complete(); } this.EventsList.clear(); this.EventEmittersList.clear(); } } public Close() { this.RemoveAllEventHandler(); this.NetTarget(NetObject.FlagDeleteObject); } }
      
      









ところで、 .NetのReactive Extensionsに関する良い記事

大食いは

Angular 2を使用せず、.Net Coreアセンブリをロードした開始ページを含むCEF。 20 mbかかります

単純なメソッドの呼び出しで、30mbに達します

動的コンパイルを接続すると、70 MBになります



Angular 2を接続すると、サイズはすぐに90 MBに達します。



しかし、動的コンパイルを使用しても、サイズは100 MBになりません



2つのガベージコレクターが機能することに注意してください。

まったく問題ありません。



メソッド呼び出しの間だけ、JSオブジェクトと関数を.Net側に転送することは難しくありません。



または、Netと同様に、JSオブジェクトのリポジトリを作成します。 幸いなことに、.Netにはファイナライザがあり、リンクのリリースを監視することはそれほど重要ではありません。



すべての開発は5人をダウンロードしましたが。 しかし、実際には、TS、C#、およびC ++と.Netの間のリンクには、プログラマーにとって多くのインターンがいます。



突然誰かが興味を持ったら、プロジェクトとソースコードをここからダウンロードできます



コンテンツの簡単な説明。 cefsimple \ Release \ディレクトリには、ライブラリとtest.htmlスタートページを含む実行可能ファイルが含まれています。 cefsimple \ NetObjectToNative \ディレクトリ内

CEFと.Net Core間の交換用のすべてのファイルがあります。 ManagedDomainLoaderとClrLoaderは、.Net Coreの読み込み、データ交換のためのメソッドの受け取りと受け渡しを行います。



CefV8HandlersForNetは、JSとCEFの間で交換するためのハンドラーを実装しています。 NetConverterで、NetとCef間のデータ変換。



NetObjectToCEFには、CEFとの交換を実装するファイルが含まれています。 TestDllForCoreClrには、すべてTestの使用例があります。



ファイルTestTypeScript \ TestTypeScript \ app \には、Proxyを実装するtsファイルがあります。 プロキシを実装するNetProxy.tsファイル。



home.component.tsはAngleSharpでテストします。 counter.component.tsさまざまな機会テスト。 TestSpeed.ts実行速度テスト。



また、node_modulesのないプロジェクト。 TestTypeScript npm installディレクトリへの呼び出しを介してインストールします。



テストの本質は次のとおりです。 TestTypeScriptおよびCefProgects \ cefsimple \ Release \ cefsimple.exeを実行します。 ホームページで、JSテストを試すことができます。 TSでテストを使用するには、「サイトアドレスを入力してください」の下のフィールドで指定する必要があるサイトに移動して、「。」に移動する必要があります。 3つのテストがあります。



cefsimpleをコンパイルする場合。 次に、ここから32ビットの標準配布をダウンロードし、tests \ cefsimple \ ccおよびhディレクトリ内のファイルを置き換えて、NetObjectToNativeディレクトリをコピーします。



VS 2015を使用するには、CEFルートディレクトリでcmake.exe -G "Visual Studio 14"と入力します。



VS 2017の場合cmake.exe -G「Visual Studio 15 2017」。



All Articles