Skip to content

Commit 7351c53

Browse files
committed
Added caching for reflection setup in ValidateAllProperties
1 parent 0437ee4 commit 7351c53

File tree

1 file changed

+20
-5
lines changed

1 file changed

+20
-5
lines changed

Microsoft.Toolkit.Mvvm/ComponentModel/ObservableValidator.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
2020
/// </summary>
2121
public abstract class ObservableValidator : ObservableObject, INotifyDataErrorInfo
2222
{
23+
/// <summary>
24+
/// The <see cref="ConditionalWeakTable{TKey,TValue}"/> instance used to track properties to validate for a given viewmodel type.
25+
/// </summary>
26+
private static readonly ConditionalWeakTable<Type, PropertyInfo[]> ValidatableProperties = new();
27+
2328
/// <summary>
2429
/// The cached <see cref="PropertyChangedEventArgs"/> for <see cref="HasErrors"/>.
2530
/// </summary>
@@ -395,11 +400,21 @@ IEnumerable<ValidationResult> GetAllErrors()
395400
/// </remarks>
396401
protected void ValidateAllProperties()
397402
{
398-
foreach (PropertyInfo propertyInfo in
399-
GetType()
400-
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
401-
.Where(static p => p.GetIndexParameters().Length == 0 &&
402-
p.GetCustomAttributes<ValidationAttribute>(true).Any()))
403+
// Helper method to discover all the properties to validate in the current viewmodel type
404+
static PropertyInfo[] GetValidatableProperties(Type type)
405+
{
406+
return (
407+
from property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
408+
where property.GetIndexParameters().Length == 0 &&
409+
property.GetCustomAttributes<ValidationAttribute>(true).Any()
410+
select property).ToArray();
411+
}
412+
413+
// Get or compute the cached list of properties to validate. Here we're using a static lambda to ensure the
414+
// delegate is cached by the C# compiler, see the related issue at https://github.com/dotnet/roslyn/issues/5835.
415+
PropertyInfo[] propertyInfos = ValidatableProperties.GetValue(GetType(), static t => GetValidatableProperties(t));
416+
417+
foreach (PropertyInfo propertyInfo in propertyInfos)
403418
{
404419
object? propertyValue = propertyInfo.GetValue(this);
405420

0 commit comments

Comments
 (0)