Skip to content

Commit 7d2e4c4

Browse files
committed
Cache reflection for reading component properties
1 parent d1b7b61 commit 7d2e4c4

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

src/Components/Components/src/SupplyParameterFromPersistentComponentStateValueProvider.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
using System.Globalization;
99
using System.Security.Cryptography;
1010
using System.Text;
11+
using Microsoft.AspNetCore.Components.Reflection;
1112
using Microsoft.AspNetCore.Components.Rendering;
1213

1314
namespace Microsoft.AspNetCore.Components;
1415

1516
internal sealed class SupplyParameterFromPersistentComponentStateValueProvider(PersistentComponentState state) : ICascadingValueSupplier
1617
{
1718
private static readonly ConcurrentDictionary<(string, string, string), byte[]> _keyCache = new();
19+
private static readonly ConcurrentDictionary<(Type, string), PropertyGetter> _propertyGetterCache = new();
20+
1821
private readonly Dictionary<ComponentState, PersistingComponentStateSubscription> _subscriptions = [];
1922

2023
public bool IsFixed => false;
@@ -61,12 +64,31 @@ public void Subscribe(ComponentState subscriber, in CascadingParameterInfo param
6164
_subscriptions[subscriber] = state.RegisterOnPersisting(() =>
6265
{
6366
var storageKey = ComputeKey(subscriber, propertyName);
64-
var property = subscriber.Component.GetType().GetProperty(propertyName)!.GetValue(subscriber.Component)!;
67+
var propertyGetter = ResolvePropertyGetter(subscriber.Component.GetType(), propertyName);
68+
var property = propertyGetter.GetValue(subscriber.Component);
69+
if (property == null)
70+
{
71+
return Task.CompletedTask;
72+
}
6573
state.PersistAsJson(storageKey, property, propertyType);
6674
return Task.CompletedTask;
6775
}, subscriber.Renderer.GetComponentRenderMode(subscriber.Component));
6876
}
6977

78+
private static PropertyGetter ResolvePropertyGetter(Type type, string propertyName)
79+
{
80+
return _propertyGetterCache.GetOrAdd((type, propertyName), (key) =>
81+
{
82+
var (type, propertyName) = key;
83+
var propertyInfo = type.GetProperty(propertyName);
84+
if (propertyInfo == null)
85+
{
86+
throw new InvalidOperationException($"Property {propertyName} not found on type {type.FullName}");
87+
}
88+
return new PropertyGetter(type, propertyInfo);
89+
});
90+
}
91+
7092
public void Unsubscribe(ComponentState subscriber, in CascadingParameterInfo parameterInfo)
7193
{
7294
if (_subscriptions.TryGetValue(subscriber, out var subscription))

0 commit comments

Comments
 (0)