Nell'ultimo video Rx squadra Bart De Smet: Rx Update - .NET 4.5, Async, WinRT ho visto che gli eventi WinRT esposti a .NET da parte di alcuni davvero strano metadati, più preciesly - add_
/remove_
metodi paio firma:come gli eventi WinRT sono interoperare con .NET
EventRegistrationToken add_MyEvent(EventHandler<MyEventArgs> handler) { … }
void remove_MyEvent(EventRegistrationToken registrationToken) { … }
Sembra davvero eccezionale, consentendo l'annullamento dell'iscrizione dall'evento "disponendo" il token di registrazione (Rx fa lo stesso tipo di cosa, restituendo l'istanza IDisposable
dal metodo Subscribe()
). Quindi è diventato possibile cancellare facilmente le espressioni di lamba dagli eventi, ma ...
Quindi, come C# consente di lavorare con questo tipo di eventi? In .NET è possibile sottoscrivere un metodo (statico e istanza) con un'istanza su delegato e annullare l'iscrizione con completamente un'altra istanza di delegato che punta allo stesso metodo. Quindi, se utilizzo un evento WinRT e semplicemente annullo l'iscrizione di qualche istanza di tipo delegato in C# ... dove il compilatore ha ottenuto il corretto EventRegistrationToken
? Come funziona tutta questa magia?
- aggiornamento -
realtà EventRegistrationToken
non permette di annullare l'iscrizione è sufficiente chiamare un qualche tipo di Dispose()
metodo, che è veramente 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()
}
- Update2 -
L'interoperabilità WinRT utilizza attualmente la tabella di registrazione globale token di gestione quando si sottoscrivono eventi WinRT con oggetti gestiti. Ad esempio, il codice di interoperabilità per la rimozione di gestori di simile a questa:
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);
}
che è davvero triste.
Nota che tutto ciò che hai descritto è un dettaglio di implementazione e può essere modificato in qualsiasi momento. Non dovresti MAI fare affidamento su alcun comportamento da te decodificato. –