Rx チームの Bart De Smet による最新のビデオ: Rx Update - .NET 4.5 , Async, WinRT私は、WinRT イベントがいくつかの非常に奇妙なメタデータによって .NET に公開されているのを見ました。add_
remove_
EventRegistrationToken add_MyEvent(EventHandler<MyEventArgs> handler) { … }
void remove_MyEvent(EventRegistrationToken registrationToken) { … }
登録トークンを「破棄」することでイベントからのサブスクライブを解除できます (Rx は同じ種類のことを行い、メソッドIDisposable
からインスタンスを返しますSubscribe()
)。ということで簡単にランバ式をイベントからサブスクライブ解除できるようになったのですが…
では、C# ではこの種のイベントをどのように操作できるのでしょうか? .NET では、デリゲートの 1 つのインスタンスでメソッド (静的およびインスタンス) をサブスクライブし、同じメソッドを指す完全に別のデリゲート インスタンスでサブスクライブを解除することができます。したがって、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<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);
}
それは本当に悲しいことです。