Csharp/C#教程:WinRT事件如何与.NET互操作分享


WinRT事件如何与.NET互操作

在Rx团队Bart De Smet的最新video中:Rx Update – .NET 4.5,Async,WinRT我看到一些非常奇怪的元数据暴露给.NET的WinRT事件,更多的是prenexly – add_ / remove_ pair方法签名:

 EventRegistrationToken add_MyEvent(EventHandler handler) { … } void remove_MyEvent(EventRegistrationToken registrationToken) { … } 

它看起来非常棒,允许通过“处理”注册令牌取消订阅事件(Rx做同样的事情,从Subscribe()方法返回IDisposable实例)。 因此,可以轻松取消订阅事件中的lamba表达式,但……

那么C#如何允许处理这类事件呢? 在.NET中,可以使用委托上的一个实例订阅方法(静态和实例),并使用指向同一方法的完全另一个委托实例取消订阅。 因此,如果我使用WinRT事件并且只是在C#中取消订阅某个委托类型实例…编译器在哪里获得正确的EventRegistrationToken ? 所有这些魔法如何运作?

– 更新 –

实际上EventRegistrationToken不允许简单地通过调用某种Dispose()方法取消订阅,这真的很遗憾:

 public struct EventRegistrationToken { internal ulong Value { get; } internal EventRegistrationToken(ulong value) public static bool operator ==(EventRegistrationToken left, EventRegistrationToken right) public static bool operator !=(EventRegistrationToken left, EventRegistrationToken right) public override bool Equals(object obj) public override int GetHashCode() } 

– update2 –

当使用托管对象订阅WinRT事件时,WinRT互操作性实际上使用全局注册令牌表。 例如,用于删除处理程序的互操作代码如下所示:

 internal static void RemoveEventHandler(Action removeMethod, T handler) { object target = removeMethod.Target; var eventRegistrationTokenTable = WindowsRuntimeMarshal.ManagedEventRegistrationImpl.GetEventRegistrationTokenTable(target, removeMethod); EventRegistrationToken obj2; lock (eventRegistrationTokenTable) { List list; if (!eventRegistrationTokenTable.TryGetValue(handler, out list)) return; if (list == null || list.Count == 0) return; int index = list.Count - 1; obj2 = list[index]; list.RemoveAt(index); } removeMethod(obj2); } 

这真的很遗憾。

当您向WinRT事件添加或删除委托时,如下所示:

 this.Loaded += MainPage_Loaded; this.Loaded -= MainPage_Loaded; 

看起来就像你正在使用普通的.Net事件一样。 但是这段代码实际上编译成这样的东西(Reflector似乎在反编译WinRT代码时遇到了一些麻烦,但我认为这就是代码实际上做的事情):

 WindowsRuntimeMarshal.AddEventHandler( new Func(this.add_Loaded), new Action(remove_Loaded), new RoutedEventHandler(this.MainPage_Loaded)); WindowsRuntimeMarshal.RemoveEventHandler( new Action(this.remove_Loaded), new RoutedEventHandler(this.MainPage_Loaded)); 

此代码实际上不会编译,因为您无法从C#访问add_remove_方法。 但你可以在IL中,这正是编译器所做的。

看起来WindosRuntimeMarshal会保留所有EventRegistrationToken并在必要时使用它们取消订阅。

你会接受“有一些非常聪明的人在研究C#语言投影”作为答案吗?

更严重的是,您发现的是事件模式的低级ABI(二进制)实现,C#语言投影知道这种模式并知道如何将其作为C#事件公开。 CLR中有一些实现此映射的类。

上述就是C#学习教程:WinRT事件如何与.NET互操作分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/988165.html

(0)
上一篇 2021年12月23日
下一篇 2021年12月23日

精彩推荐