在Rx团队最新的视频Bart De Smet: Rx Update - .NET 4.5, Async, WinRT中,我发现WinRT事件通过一些非常奇怪的元数据暴露给了.NET,更确切地说是
这看起来非常棒,可以通过“处理”注册令牌(Rx也采用同样的方法,从
--更新--
实际上,
这真的很不幸。
add_
/remove_
配对方法的签名:EventRegistrationToken add_MyEvent(EventHandler<MyEventArgs> handler) { … }
void remove_MyEvent(EventRegistrationToken registrationToken) { … }
这看起来非常棒,可以通过“处理”注册令牌(Rx也采用同样的方法,从
Subscribe()
方法返回实例)来取消事件订阅。因此,现在可以轻松地取消来自事件的lambda表达式,但是......C#如何允许使用此类事件?在.NET中,可以使用一个委托实例订阅一个方法(静态和实例),并使用完全不同的指向相同方法的委托实例取消订阅。那么如果我只是在C#中使用WinRT事件并取消某个委托类型实例的订阅...编译器从哪里获取正确的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()
}
-- 更新2 --
WinRT互操作性实际上使用全局注册令牌表来订阅带有托管对象的WinRT事件。例如,删除处理程序的交互操作代码如下:
internal static void RemoveEventHandler<T>(Action<EventRegistrationToken> removeMethod, T handler)
{
object target = removeMethod.Target;
var eventRegistrationTokenTable = WindowsRuntimeMarshal.ManagedEventRegistrationImpl.GetEventRegistrationTokenTable(target, removeMethod);
EventRegistrationToken obj2;
lock (eventRegistrationTokenTable)
{
List<EventRegistrationToken> 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);
}
这真的很不幸。