Browse Source

Compiled expressions for RoutedEvent.

pull/2943/head
Dariusz Komosinski 7 years ago
parent
commit
04c2dfcc54
  1. 4
      src/Avalonia.Interactivity/EventSubscription.cs
  2. 26
      src/Avalonia.Interactivity/Interactive.cs

4
src/Avalonia.Interactivity/EventSubscription.cs

@ -5,8 +5,12 @@ using System;
namespace Avalonia.Interactivity
{
internal delegate void InvokeSignature(Delegate func, object sender, RoutedEventArgs args);
internal class EventSubscription
{
public InvokeSignature RaiseHandler { get; set; }
public Delegate Handler { get; set; }
public RoutingStrategies Routes { get; set; }

26
src/Avalonia.Interactivity/Interactive.cs

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using Avalonia.Layout;
@ -28,6 +29,10 @@ namespace Avalonia.Interactivity
get { return _eventHandlers ?? (_eventHandlers = new Dictionary<RoutedEvent, List<EventSubscription>>()); }
}
private static Dictionary<Type, InvokeSignature> s_invokeCache = new Dictionary<Type, InvokeSignature>();
/// <summary>
/// Adds a handler for the specified routed event.
/// </summary>
@ -53,8 +58,27 @@ namespace Avalonia.Interactivity
EventHandlers.Add(routedEvent, subscriptions);
}
if (!s_invokeCache.TryGetValue(routedEvent.EventArgsType, out InvokeSignature raiseFunc))
{
ParameterExpression funcParameter = Expression.Parameter(typeof(Delegate), "func");
ParameterExpression senderParameter = Expression.Parameter(typeof(object), "sender");
ParameterExpression argsParameter = Expression.Parameter(typeof(RoutedEventArgs), "args");
UnaryExpression convertedFunc = Expression.Convert(funcParameter, typeof(EventHandler<>).MakeGenericType(routedEvent.EventArgsType));
UnaryExpression convertedArgs = Expression.Convert(argsParameter, routedEvent.EventArgsType);
InvocationExpression invokeDelegate = Expression.Invoke(convertedFunc, senderParameter, convertedArgs);
raiseFunc = Expression
.Lambda<InvokeSignature>(invokeDelegate, funcParameter, senderParameter, argsParameter)
.Compile();
s_invokeCache.Add(routedEvent.EventArgsType, raiseFunc);
}
var sub = new EventSubscription
{
RaiseHandler = raiseFunc,
Handler = handler,
Routes = routes,
AlsoIfHandled = handledEventsToo,
@ -196,7 +220,7 @@ namespace Avalonia.Interactivity
if (correctRoute && notFinished)
{
sub.Handler.DynamicInvoke(this, e);
sub.RaiseHandler(sub.Handler, this, e);
}
}
}

Loading…
Cancel
Save