En el último vídeo por Rx equipo Bart De Smet: Rx Update - .NET 4.5, Async, WinRT vi que los eventos WinRT expuestos a .NET por algunos metadatos realmente extraño, más preciesly - add_
/remove_
métodos par firma:eventos WinRT se interoperar con .NET
EventRegistrationToken add_MyEvent(EventHandler<MyEventArgs> handler) { … }
void remove_MyEvent(EventRegistrationToken registrationToken) { … }
Parece realmente genial, lo que permite anular la suscripción al evento "desechando" el token de registro (Rx hace el mismo tipo de cosas, devolviendo la instancia IDisposable
del método Subscribe()
). Por lo tanto, es posible cancelar fácilmente la suscripción a expresiones lamba de eventos, pero ...
Entonces, ¿cómo C# permite trabajar con este tipo de eventos? En .NET es posible suscribir un método (estático y de instancia) con una instancia en el delegado y anular la suscripción con otra instancia delegada completamente apuntada al mismo método. Entonces, si utilizo un evento WinRT y simplemente cancelo la suscripción de alguna instancia de tipo de delegado en C# ... ¿de dónde obtuvo el compilador el EventRegistrationToken
correcto? ¿Cómo funciona toda esta magia?
- Actualización -
En realidad EventRegistrationToken
no permite darse de baja, simplemente llamando a algún tipo de Dispose()
método, que es realmente triste:
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()
}
- Actualización 2 -
Interoperabilidad WinRT en realidad usa global tabla de registro Tokens de señalización cuando se suscriben eventos WinRT con objetos administrados. Por ejemplo, el código de interoperabilidad para eliminar controladores se ve así:
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);
}
Eso es realmente triste.
Tenga en cuenta que todo lo que ha descrito es un detalle de la implementación y puede modificarse en cualquier momento. NUNCA debes confiar en ningún comportamiento que utilices para la ingeniería inversa. –