Browse Source

Allow for setting up deferred setter notify handlers without extra allocations.

pull/2933/head
Dariusz Komosiński 7 years ago
parent
commit
11298df527
  1. 14
      src/Avalonia.Base/PriorityValue.cs
  2. 30
      src/Avalonia.Base/Utilities/DeferredSetter.cs

14
src/Avalonia.Base/PriorityValue.cs

@ -24,13 +24,11 @@ namespace Avalonia
/// <see cref="IPriorityValueOwner.Changed"/> method on the
/// owner object is fired with the old and new values.
/// </remarks>
internal class PriorityValue
internal sealed class PriorityValue : ISetAndNotifyHandler<(object,int)>
{
private readonly Type _valueType;
private readonly SingleOrDictionary<int, PriorityLevel> _levels = new SingleOrDictionary<int, PriorityLevel>();
private readonly Func<object, object> _validate;
private readonly SetAndNotifyCallback<(object, int)> _setAndNotifyCallback;
private (object value, int priority) _value;
private DeferredSetter<object> _setter;
@ -52,7 +50,6 @@ namespace Avalonia
_valueType = valueType;
_value = (AvaloniaProperty.UnsetValue, int.MaxValue);
_validate = validate;
_setAndNotifyCallback = SetAndNotify;
}
/// <summary>
@ -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;

30
src/Avalonia.Base/Utilities/DeferredSetter.cs

@ -5,15 +5,6 @@ using System;
namespace Avalonia.Utilities
{
/// <summary>
/// Callback invoked when deferred setter wants to set a value.
/// </summary>
/// <typeparam name="TValue">Value type.</typeparam>
/// <param name="property">Property being set.</param>
/// <param name="backing">Backing field reference.</param>
/// <param name="value">New value.</param>
internal delegate void SetAndNotifyCallback<TValue>(AvaloniaProperty property, ref TValue backing, TValue value);
/// <summary>
/// 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<TValue>(AvaloniaProperty property, SetAndNotifyCallback<TValue> setAndNotifyCallback, ref TValue backing, TValue value)
public bool SetAndNotifyCallback<TValue>(AvaloniaProperty property, ISetAndNotifyHandler<TValue> 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
}
}
}
/// <summary>
/// Handler for set and notify requests.
/// </summary>
/// <typeparam name="TValue">Value type.</typeparam>
internal interface ISetAndNotifyHandler<TValue>
{
/// <summary>
/// Handles deferred setter requests to set a value.
/// </summary>
/// <param name="property">Property being set.</param>
/// <param name="backing">Backing field reference.</param>
/// <param name="value">New value.</param>
void HandleSetAndNotify(AvaloniaProperty property, ref TValue backing, TValue value);
}
}

Loading…
Cancel
Save