Skip to content

Commit

Permalink
feat: improve performance through caching (#115)
Browse files Browse the repository at this point in the history
  • Loading branch information
BoBoBaSs84 authored Jul 13, 2024
2 parents ce9b8dd + 809c74d commit f050aa7
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 18 deletions.
53 changes: 39 additions & 14 deletions src/BB84.Notifications/NotifiableObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ namespace BB84.Notifications;
/// </summary>
public abstract class NotifiableObject : INotifiableObject
{
private static readonly Dictionary<string, string[]> PropertyChangedAttributeCache = [];
private static readonly Dictionary<string, string[]> PropertyChangingAttributeCache = [];

/// <summary>
/// Initializes a new instance of the <see cref="NotifiableObject"/> class.
/// </summary>
protected NotifiableObject() => FillCaches();

/// <inheritdoc/>
public event PropertyChangedEventHandler? PropertyChanged;

Expand Down Expand Up @@ -79,16 +87,12 @@ protected void RaisePropertyChanging<T>(string propertyName, T value)
/// <param name="propertyName">The name of the calling property.</param>
private void RaiseChangedAttribute(string propertyName)
{
PropertyInfo? propertyInfo = GetType().GetProperty(propertyName);
bool success = PropertyChangedAttributeCache.TryGetValue(propertyName, out string[]? propertiesToNotify);

if (propertyInfo is not null)
if (success && propertiesToNotify is not null)
{
NotifyChangedAttribute? attribute =
propertyInfo.GetCustomAttribute(typeof(NotifyChangedAttribute), false) as NotifyChangedAttribute;

if (attribute is not null)
foreach (string property in attribute.Properties)
RaisePropertyChanged(property);
foreach (string propertyToNotify in propertiesToNotify)
RaisePropertyChanged(propertyToNotify);
}
}

Expand All @@ -99,16 +103,37 @@ private void RaiseChangedAttribute(string propertyName)
/// <param name="propertyName">The name of the calling property.</param>
private void RaiseChangingAttribute(string propertyName)
{
PropertyInfo? propertyInfo = GetType().GetProperty(propertyName);
bool success = PropertyChangingAttributeCache.TryGetValue(propertyName, out string[]? propertiesToNotify);

if (propertyInfo is not null)
if (success && propertiesToNotify is not null)
{
NotifyChangingAttribute? attribute =
foreach (string propertyToNotify in propertiesToNotify)
RaisePropertyChanging(propertyToNotify);
}
}

/// <summary>
/// The method fills the <see cref="PropertyChangedAttributeCache"/> and the <see cref="PropertyChangingAttributeCache"/>
/// when the class is instantiated so that it only has to do this once. This means that subsequent calls to
/// <see cref="RaiseChangedAttribute"/> and <see cref="RaiseChangingAttribute"/> no longer have to do this.
/// </summary>
private void FillCaches()
{
PropertyInfo[] propertiesInfos = GetType().GetProperties();

foreach (PropertyInfo propertyInfo in propertiesInfos)
{
NotifyChangedAttribute? changedAttribute =
propertyInfo.GetCustomAttribute(typeof(NotifyChangedAttribute), false) as NotifyChangedAttribute;

if (changedAttribute is not null)
PropertyChangedAttributeCache.Add(propertyInfo.Name, changedAttribute.Properties);

NotifyChangingAttribute? changingAttribute =
propertyInfo.GetCustomAttribute(typeof(NotifyChangingAttribute), false) as NotifyChangingAttribute;

if (attribute is not null)
foreach (string property in attribute.Properties)
RaisePropertyChanging(property);
if (changingAttribute is not null)
PropertyChangingAttributeCache.Add(propertyInfo.Name, changingAttribute.Properties);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,18 @@ public TestClass(int quantity, int value)
}

[NotifyChanged(nameof(TotalValue))]
public int Quantity { get => _quantity; set => SetProperty(ref _quantity, value); }
public int Quantity
{
get => _quantity;
set => SetProperty(ref _quantity, value);
}

[NotifyChanged(nameof(TotalValue))]
public int Value { get => _value; set => SetProperty(ref _value, value); }
public int Value
{
get => _value;
set => SetProperty(ref _value, value);
}

public int TotalValue => Quantity * Value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,18 @@ public TestClass(int quantity, int value)
}

[NotifyChanging(nameof(TotalValue))]
public int Quantity { get => _quantity; set => SetProperty(ref _quantity, value); }
public int Quantity
{
get => _quantity;
set => SetProperty(ref _quantity, value);
}

[NotifyChanging(nameof(TotalValue))]
public int Value { get => _value; set => SetProperty(ref _value, value); }
public int Value
{
get => _value;
set => SetProperty(ref _value, value);
}

public int TotalValue => Quantity * Value;
}
Expand Down

0 comments on commit f050aa7

Please sign in to comment.