|
8 | 8 | using System.Globalization; |
9 | 9 | using System.Security.Cryptography; |
10 | 10 | using System.Text; |
| 11 | +using Microsoft.AspNetCore.Components.Reflection; |
11 | 12 | using Microsoft.AspNetCore.Components.Rendering; |
12 | 13 |
|
13 | 14 | namespace Microsoft.AspNetCore.Components; |
14 | 15 |
|
15 | 16 | internal sealed class SupplyParameterFromPersistentComponentStateValueProvider(PersistentComponentState state) : ICascadingValueSupplier |
16 | 17 | { |
17 | 18 | private static readonly ConcurrentDictionary<(string, string, string), byte[]> _keyCache = new(); |
| 19 | + private static readonly ConcurrentDictionary<(Type, string), PropertyGetter> _propertyGetterCache = new(); |
| 20 | + |
18 | 21 | private readonly Dictionary<ComponentState, PersistingComponentStateSubscription> _subscriptions = []; |
19 | 22 |
|
20 | 23 | public bool IsFixed => false; |
@@ -61,12 +64,31 @@ public void Subscribe(ComponentState subscriber, in CascadingParameterInfo param |
61 | 64 | _subscriptions[subscriber] = state.RegisterOnPersisting(() => |
62 | 65 | { |
63 | 66 | 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 | + } |
65 | 73 | state.PersistAsJson(storageKey, property, propertyType); |
66 | 74 | return Task.CompletedTask; |
67 | 75 | }, subscriber.Renderer.GetComponentRenderMode(subscriber.Component)); |
68 | 76 | } |
69 | 77 |
|
| 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 | + |
70 | 92 | public void Unsubscribe(ComponentState subscriber, in CascadingParameterInfo parameterInfo) |
71 | 93 | { |
72 | 94 | if (_subscriptions.TryGetValue(subscriber, out var subscription)) |
|
0 commit comments