From 1909d7a77804d740b79874fb663b02b22edac49c Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Thu, 5 Mar 2020 00:18:46 +0100 Subject: [PATCH 1/2] Avoid IAffectsRender subscribe attempts on values that can't implement it. --- .../AvaloniaPropertyExtensions.cs | 27 +++++++++++++++++++ src/Avalonia.Visuals/Media/Brush.cs | 4 +-- src/Avalonia.Visuals/Media/Pen.cs | 20 +++++++++++--- src/Avalonia.Visuals/Visual.cs | 21 ++++++++++++--- 4 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 src/Avalonia.Visuals/AvaloniaPropertyExtensions.cs diff --git a/src/Avalonia.Visuals/AvaloniaPropertyExtensions.cs b/src/Avalonia.Visuals/AvaloniaPropertyExtensions.cs new file mode 100644 index 0000000000..6aaa224b00 --- /dev/null +++ b/src/Avalonia.Visuals/AvaloniaPropertyExtensions.cs @@ -0,0 +1,27 @@ +using Avalonia.Media; + +#nullable enable + +namespace Avalonia +{ + /// + /// Extensions for . + /// + public static class AvaloniaPropertyExtensions + { + /// + /// Checks if values of given property can affect rendering (via ). + /// + /// Property to check. + public static bool CanValueAffectRender(this AvaloniaProperty property) + { + var propertyType = property.PropertyType; + + // Only case that we are sure that property value CAN'T affect render are sealed types that don't implement + // the interface. + var cannotAffectRender = propertyType.IsSealed && !typeof(IAffectsRender).IsAssignableFrom(propertyType); + + return !cannotAffectRender; + } + } +} diff --git a/src/Avalonia.Visuals/Media/Brush.cs b/src/Avalonia.Visuals/Media/Brush.cs index f36cd88537..0d08f92685 100644 --- a/src/Avalonia.Visuals/Media/Brush.cs +++ b/src/Avalonia.Visuals/Media/Brush.cs @@ -69,14 +69,14 @@ namespace Avalonia.Media protected static void AffectsRender(params AvaloniaProperty[] properties) where T : Brush { - void Invalidate(AvaloniaPropertyChangedEventArgs e) + static void Invalidate(AvaloniaPropertyChangedEventArgs e) { (e.Sender as T)?.RaiseInvalidated(EventArgs.Empty); } foreach (var property in properties) { - property.Changed.Subscribe(Invalidate); + property.Changed.Subscribe(e => Invalidate(e)); } } diff --git a/src/Avalonia.Visuals/Media/Pen.cs b/src/Avalonia.Visuals/Media/Pen.cs index b88fae28ff..8ab2b11331 100644 --- a/src/Avalonia.Visuals/Media/Pen.cs +++ b/src/Avalonia.Visuals/Media/Pen.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; -using System.Collections.Generic; using Avalonia.Media.Immutable; using Avalonia.Utilities; @@ -197,7 +196,15 @@ namespace Avalonia.Media protected static void AffectsRender(params AvaloniaProperty[] properties) where T : Pen { - void Invalidate(AvaloniaPropertyChangedEventArgs e) + static void Invalidate(AvaloniaPropertyChangedEventArgs e) + { + if (e.Sender is T sender) + { + sender.RaiseInvalidated(EventArgs.Empty); + } + } + + static void InvalidateAndSubscribe(AvaloniaPropertyChangedEventArgs e) { if (e.Sender is T sender) { @@ -223,7 +230,14 @@ namespace Avalonia.Media foreach (var property in properties) { - property.Changed.Subscribe(Invalidate); + if (property.CanValueAffectRender()) + { + property.Changed.Subscribe(e => InvalidateAndSubscribe(e)); + } + else + { + property.Changed.Subscribe(e => Invalidate(e)); + } } } diff --git a/src/Avalonia.Visuals/Visual.cs b/src/Avalonia.Visuals/Visual.cs index bd2ab6e614..018af060c1 100644 --- a/src/Avalonia.Visuals/Visual.cs +++ b/src/Avalonia.Visuals/Visual.cs @@ -336,7 +336,15 @@ namespace Avalonia protected static void AffectsRender(params AvaloniaProperty[] properties) where T : Visual { - void Invalidate(AvaloniaPropertyChangedEventArgs e) + static void Invalidate(AvaloniaPropertyChangedEventArgs e) + { + if (e.Sender is T sender) + { + sender.InvalidateVisual(); + } + } + + static void InvalidateAndSubscribe(AvaloniaPropertyChangedEventArgs e) { if (e.Sender is T sender) { @@ -347,7 +355,7 @@ namespace Avalonia if (e.NewValue is IAffectsRender newValue) { - WeakEventHandlerManager.Subscribe(newValue, nameof(newValue.Invalidated), sender.AffectsRenderInvalidated); + WeakEventHandlerManager.Subscribe(newValue, nameof(newValue.Invalidated), sender.AffectsRenderInvalidated); } sender.InvalidateVisual(); @@ -356,7 +364,14 @@ namespace Avalonia foreach (var property in properties) { - property.Changed.Subscribe(Invalidate); + if (property.CanValueAffectRender()) + { + property.Changed.Subscribe(e => InvalidateAndSubscribe(e)); + } + else + { + property.Changed.Subscribe(e => Invalidate(e)); + } } } From 1027168c61e7b5342620941889abbc25d502fa9b Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Thu, 5 Mar 2020 00:29:37 +0100 Subject: [PATCH 2/2] Remove omen of bad performance. --- src/Avalonia.Visuals/Visual.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Avalonia.Visuals/Visual.cs b/src/Avalonia.Visuals/Visual.cs index 018af060c1..d9032cfa3e 100644 --- a/src/Avalonia.Visuals/Visual.cs +++ b/src/Avalonia.Visuals/Visual.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Specialized; -using System.Linq; using Avalonia.Collections; using Avalonia.Data; using Avalonia.Logging;