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