Browse Source

Merge pull request #2127 from AvaloniaUI/perf/cache-ao-initialization

[Perf] Cache AvaloniaObject initialization notifications.
pull/2321/head
Steven Kirk 7 years ago
committed by GitHub
parent
commit
fe74dfe538
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  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
{
@ -23,6 +24,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
@ -226,6 +229,7 @@ namespace Avalonia
}
_registeredCache.Clear();
_initializedCache.Clear();
}
/// <summary>
@ -261,6 +265,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