Repository: dotnet/aspnetcore
File: src/Components/Components/src/Reflection/ComponentProperties.cs (C#)

Code before:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Components.HotReload;
using static Microsoft.AspNetCore.Internal.LinkerFlags;

namespace Microsoft.AspNetCore.Components.Reflection;

internal static class ComponentProperties
{
    static ComponentProperties() => HotReloadManager.Default.OnDeltaApplied += ClearCache;

    internal const BindingFlags BindablePropertyFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase;

    // Right now it's not possible for a component to define a Parameter and a Cascading Parameter with
    // the same name. We don't give you a way to express this in code (would create duplicate properties),
    // and we don't have the ability to represent it in our data structures.
    private static readonly ConcurrentDictionary<Type, WritersForType> _cachedWritersByType
        = new ConcurrentDictionary<Type, WritersForType>();

    public static void ClearCache() => _cachedWritersByType.Clear();

    public static void SetProperties(in ParameterView parameters, object target)
    {
        ArgumentNullException.ThrowIfNull(target);

        var targetType = target.GetType();
        if (!_cachedWritersByType.TryGetValue(targetType, out var writers))
        {
            // Suppressed with "pragma warning disable" so ILLink Roslyn Anayzer doesn't report the warning.
            #pragma warning disable IL2072 // 'targetType' argument does not satisfy 'DynamicallyAccessedMemberTypes.All' in call to 'Microsoft.AspNetCore.Components.Reflection.ComponentProperties.WritersForType.WritersForType(Type)'.
            writers = new WritersForType(targetType);
            #pragma warning restore IL2072 // 'targetType' argument does not satisfy 'DynamicallyAccessedMemberTypes.All' in call to 'Microsoft.AspNetCore.Components.Reflection.ComponentProperties.WritersForType.WritersForType(Type)'.
            _cachedWritersByType[targetType] = writers;
        }


Review comment (performance):
```suggestion
    static ComponentProperties()
    {
        if (HotReloadManager.Default.MetadataUpdateSupported)
        {
            HotReloadManager.Default.OnDeltaApplied += ClearCache;
        }
    }
```

Code after:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Components.HotReload;
using static Microsoft.AspNetCore.Internal.LinkerFlags;

namespace Microsoft.AspNetCore.Components.Reflection;

internal static class ComponentProperties
{
    static ComponentProperties()
    {
        if (HotReloadManager.Default.MetadataUpdateSupported)
        {
            HotReloadManager.Default.OnDeltaApplied += ClearCache;
        }
    }

    internal const BindingFlags BindablePropertyFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase;

    // Right now it's not possible for a component to define a Parameter and a Cascading Parameter with
    // the same name. We don't give you a way to express this in code (would create duplicate properties),
    // and we don't have the ability to represent it in our data structures.
    private static readonly ConcurrentDictionary<Type, WritersForType> _cachedWritersByType
        = new ConcurrentDictionary<Type, WritersForType>();

    public static void ClearCache() => _cachedWritersByType.Clear();

    public static void SetProperties(in ParameterView parameters, object target)
    {
        ArgumentNullException.ThrowIfNull(target);

        var targetType = target.GetType();
        if (!_cachedWritersByType.TryGetValue(targetType, out var writers))
        {
            // Suppressed with "pragma warning disable" so ILLink Roslyn Anayzer doesn't report the warning.