From bc938eabba57b603527f2e3ba97c276885a572a2 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Sat, 29 Feb 2020 14:49:07 +0100 Subject: [PATCH] Let the compiler to emit handler lookup for us. Get rid of extra closure when removing handlers. --- src/Avalonia.Interactivity/Interactive.cs | 35 +++++++++-------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/src/Avalonia.Interactivity/Interactive.cs b/src/Avalonia.Interactivity/Interactive.cs index 6992ebcf34..f39c689c4c 100644 --- a/src/Avalonia.Interactivity/Interactive.cs +++ b/src/Avalonia.Interactivity/Interactive.cs @@ -15,9 +15,6 @@ namespace Avalonia.Interactivity { private Dictionary>? _eventHandlers; - private static readonly Dictionary> s_invokeHandlerCache - = new Dictionary>(); - /// /// Gets the interactive parent of the object for bubbling and tunneling events. /// @@ -62,26 +59,16 @@ namespace Avalonia.Interactivity routedEvent = routedEvent ?? throw new ArgumentNullException(nameof(routedEvent)); handler = handler ?? throw new ArgumentNullException(nameof(handler)); - // EventHandler delegate is not covariant, this forces us to create small wrapper - // that will cast our type erased instance and invoke it. - var eventArgsType = routedEvent.EventArgsType; - - if (!s_invokeHandlerCache.TryGetValue(eventArgsType, out var invokeAdapter)) + static void InvokeAdapter(Delegate baseHandler, object sender, RoutedEventArgs args) { - void InvokeAdapter(Delegate baseHandler, object sender, RoutedEventArgs args) - { - var typedHandler = (EventHandler)baseHandler; - var typedArgs = (TEventArgs)args; - - typedHandler(sender, typedArgs); - } - - invokeAdapter = InvokeAdapter; + var typedHandler = (EventHandler)baseHandler; + var typedArgs = (TEventArgs)args; - s_invokeHandlerCache.Add(eventArgsType, invokeAdapter); + typedHandler(sender, typedArgs); } - var subscription = new EventSubscription(handler, routes, handledEventsToo, invokeAdapter); + var subscription = new EventSubscription(handler, routes, handledEventsToo, (baseHandler, sender, args) => InvokeAdapter(baseHandler, sender, args)); + return AddEventSubscription(routedEvent, subscription); } @@ -96,9 +83,15 @@ namespace Avalonia.Interactivity handler = handler ?? throw new ArgumentNullException(nameof(handler)); if (_eventHandlers is object && - _eventHandlers.TryGetValue(routedEvent, out var subscriptions) == true) + _eventHandlers.TryGetValue(routedEvent, out var subscriptions)) { - subscriptions.RemoveAll(x => x.Handler == handler); + for (var i = subscriptions.Count - 1; i >= 0; i--) + { + if (subscriptions[i].Handler == handler) + { + subscriptions.RemoveAt(i); + } + } } }