Browse Source

Cache AvaloniaObject initialization notifications.

When an `AvaloniaObject` is created, it notifies each of the `AvaloniaProperties` registered on it that they have been initialized on a new object. Instead of calling `GetDefaultValue` each time, cache the default values.
pull/2127/head
Steven Kirk 8 years ago
parent
commit
97db5ec657
  1. 46
      src/Avalonia.Base/AvaloniaObject.cs
  2. 55
      src/Avalonia.Base/AvaloniaPropertyRegistry.cs

46
src/Avalonia.Base/AvaloniaObject.cs

@ -22,27 +22,10 @@ namespace Avalonia
/// </remarks>
public class AvaloniaObject : IAvaloniaObject, IAvaloniaObjectDebug, INotifyPropertyChanged
{
/// <summary>
/// The parent object that inherited values are inherited from.
/// </summary>
private IAvaloniaObject _inheritanceParent;
/// <summary>
/// Maintains a list of direct property binding subscriptions so that the binding source
/// doesn't get collected.
/// </summary>
private List<DirectBindingSubscription> _directBindings;
/// <summary>
/// Event handler for <see cref="INotifyPropertyChanged"/> implementation.
/// </summary>
private PropertyChangedEventHandler _inpcChanged;
/// <summary>
/// Event handler for <see cref="PropertyChanged"/> implementation.
/// </summary>
private EventHandler<AvaloniaPropertyChangedEventArgs> _propertyChanged;
private ValueStore _values;
private ValueStore Values => _values ?? (_values = new ValueStore(this));
@ -52,32 +35,7 @@ namespace Avalonia
public AvaloniaObject()
{
VerifyAccess();
void Notify(AvaloniaProperty property)
{
object value = property.IsDirect ?
((IDirectPropertyAccessor)property).GetValue(this) :
((IStyledPropertyAccessor)property).GetDefaultValue(GetType());
var e = new AvaloniaPropertyChangedEventArgs(
this,
property,
AvaloniaProperty.UnsetValue,
value,
BindingPriority.Unset);
property.NotifyInitialized(e);
}
foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegistered(this))
{
Notify(property);
}
foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegisteredAttached(this.GetType()))
{
Notify(property);
}
AvaloniaPropertyRegistry.Instance.NotifyInitialized(this);
}
/// <summary>
@ -628,7 +586,7 @@ namespace Avalonia
/// </summary>
/// <param name="property">The property.</param>
/// <returns>The default value.</returns>
internal object GetDefaultValue(AvaloniaProperty property)
private object GetDefaultValue(AvaloniaProperty property)
{
if (property.Inherits && InheritanceParent is AvaloniaObject aobj)
return aobj.GetValue(property);

55
src/Avalonia.Base/AvaloniaPropertyRegistry.cs

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Avalonia.Data;
namespace Avalonia
{
@ -21,6 +22,8 @@ namespace Avalonia
new Dictionary<Type, List<AvaloniaProperty>>();
private readonly Dictionary<Type, List<AvaloniaProperty>> _attachedCache =
new Dictionary<Type, List<AvaloniaProperty>>();
private readonly Dictionary<Type, List<KeyValuePair<AvaloniaProperty, object>>> _initializedCache =
new Dictionary<Type, List<KeyValuePair<AvaloniaProperty, object>>>();
/// <summary>
/// Gets the <see cref="AvaloniaPropertyRegistry"/> instance
@ -204,6 +207,7 @@ namespace Avalonia
}
_registeredCache.Clear();
_initializedCache.Clear();
}
/// <summary>
@ -239,6 +243,57 @@ namespace Avalonia
}
_attachedCache.Clear();
_initializedCache.Clear();
}
internal void NotifyInitialized(AvaloniaObject o)
{
Contract.Requires<ArgumentNullException>(o != null);
var type = o.GetType();
void Notify(AvaloniaProperty property, object value)
{
var e = new AvaloniaPropertyChangedEventArgs(
o,
property,
AvaloniaProperty.UnsetValue,
value,
BindingPriority.Unset);
property.NotifyInitialized(e);
}
if (!_initializedCache.TryGetValue(type, out var items))
{
var build = new Dictionary<AvaloniaProperty, object>();
foreach (var property in GetRegistered(type))
{
var value = !property.IsDirect ?
((IStyledPropertyAccessor)property).GetDefaultValue(type) :
null;
build.Add(property, value);
}
foreach (var property in GetRegisteredAttached(type))
{
if (!build.ContainsKey(property))
{
var value = ((IStyledPropertyAccessor)property).GetDefaultValue(type);
build.Add(property, value);
}
}
items = build.ToList();
_initializedCache.Add(type, items);
}
foreach (var i in items)
{
var value = i.Key.IsDirect ? o.GetValue(i.Key) : i.Value;
Notify(i.Key, value);
}
}
}
}

Loading…
Cancel
Save