From 11298df527718bc4466e08d51b3b70e4a2c10e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20Komosi=C5=84ski?= Date: Fri, 6 Sep 2019 14:26:19 +0200 Subject: [PATCH] Allow for setting up deferred setter notify handlers without extra allocations. --- src/Avalonia.Base/PriorityValue.cs | 14 +++++---- src/Avalonia.Base/Utilities/DeferredSetter.cs | 30 +++++++++++-------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.Base/PriorityValue.cs b/src/Avalonia.Base/PriorityValue.cs index 4996420fe7..2871271062 100644 --- a/src/Avalonia.Base/PriorityValue.cs +++ b/src/Avalonia.Base/PriorityValue.cs @@ -24,13 +24,11 @@ namespace Avalonia /// method on the /// owner object is fired with the old and new values. /// - internal class PriorityValue + internal sealed class PriorityValue : ISetAndNotifyHandler<(object,int)> { private readonly Type _valueType; private readonly SingleOrDictionary _levels = new SingleOrDictionary(); - private readonly Func _validate; - private readonly SetAndNotifyCallback<(object, int)> _setAndNotifyCallback; private (object value, int priority) _value; private DeferredSetter _setter; @@ -52,7 +50,6 @@ namespace Avalonia _valueType = valueType; _value = (AvaloniaProperty.UnsetValue, int.MaxValue); _validate = validate; - _setAndNotifyCallback = SetAndNotify; } /// @@ -257,10 +254,15 @@ namespace Avalonia _setter = Owner.GetNonDirectDeferredSetter(Property); } - _setter.SetAndNotifyCallback(Property, _setAndNotifyCallback, ref _value, newValue); + _setter.SetAndNotifyCallback(Property, this, ref _value, newValue); + } + + void ISetAndNotifyHandler<(object, int)>.HandleSetAndNotify(AvaloniaProperty property, ref (object, int) backing, (object, int) value) + { + SetAndNotify(ref backing, value); } - private void SetAndNotify(AvaloniaProperty property, ref (object value, int priority) backing, (object value, int priority) update) + private void SetAndNotify(ref (object value, int priority) backing, (object value, int priority) update) { var val = update.value; var notification = val as BindingNotification; diff --git a/src/Avalonia.Base/Utilities/DeferredSetter.cs b/src/Avalonia.Base/Utilities/DeferredSetter.cs index fd7a66fb52..fe9b0e58a0 100644 --- a/src/Avalonia.Base/Utilities/DeferredSetter.cs +++ b/src/Avalonia.Base/Utilities/DeferredSetter.cs @@ -5,15 +5,6 @@ using System; namespace Avalonia.Utilities { - /// - /// Callback invoked when deferred setter wants to set a value. - /// - /// Value type. - /// Property being set. - /// Backing field reference. - /// New value. - internal delegate void SetAndNotifyCallback(AvaloniaProperty property, ref TValue backing, TValue value); - /// /// A utility class to enable deferring assignment until after property-changed notifications are sent. /// Used to fix #855. @@ -70,14 +61,14 @@ namespace Avalonia.Utilities return false; } - public bool SetAndNotifyCallback(AvaloniaProperty property, SetAndNotifyCallback setAndNotifyCallback, ref TValue backing, TValue value) + public bool SetAndNotifyCallback(AvaloniaProperty property, ISetAndNotifyHandler setAndNotifyHandler, ref TValue backing, TValue value) where TValue : TSetRecord { if (!_isNotifying) { using (new NotifyDisposable(this)) { - setAndNotifyCallback(property, ref backing, value); + setAndNotifyHandler.HandleSetAndNotify(property, ref backing, value); } if (!_pendingValues.Empty) @@ -86,7 +77,7 @@ namespace Avalonia.Utilities { while (!_pendingValues.Empty) { - setAndNotifyCallback(property, ref backing, (TValue) _pendingValues.Dequeue()); + setAndNotifyHandler.HandleSetAndNotify(property, ref backing, (TValue)_pendingValues.Dequeue()); } } } @@ -119,4 +110,19 @@ namespace Avalonia.Utilities } } } + + /// + /// Handler for set and notify requests. + /// + /// Value type. + internal interface ISetAndNotifyHandler + { + /// + /// Handles deferred setter requests to set a value. + /// + /// Property being set. + /// Backing field reference. + /// New value. + void HandleSetAndNotify(AvaloniaProperty property, ref TValue backing, TValue value); + } }