diff --git a/src/Components/Authorization/src/AttributeAuthorizeDataCache.cs b/src/Components/Authorization/src/AttributeAuthorizeDataCache.cs index 1181537155cc..6f7f4bd06539 100644 --- a/src/Components/Authorization/src/AttributeAuthorizeDataCache.cs +++ b/src/Components/Authorization/src/AttributeAuthorizeDataCache.cs @@ -3,13 +3,24 @@ using System.Collections.Concurrent; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Components.HotReload; namespace Microsoft.AspNetCore.Components.Authorization; internal static class AttributeAuthorizeDataCache { + static AttributeAuthorizeDataCache() + { + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += ClearCache; + } + } + private static readonly ConcurrentDictionary _cache = new(); + private static void ClearCache() => _cache.Clear(); + public static IAuthorizeData[]? GetAuthorizeDataForType(Type type) { if (!_cache.TryGetValue(type, out var result)) diff --git a/src/Components/Authorization/src/Microsoft.AspNetCore.Components.Authorization.csproj b/src/Components/Authorization/src/Microsoft.AspNetCore.Components.Authorization.csproj index 53340c6d6159..cef47c8d844d 100644 --- a/src/Components/Authorization/src/Microsoft.AspNetCore.Components.Authorization.csproj +++ b/src/Components/Authorization/src/Microsoft.AspNetCore.Components.Authorization.csproj @@ -14,4 +14,8 @@ + + + + diff --git a/src/Components/Components/src/BindConverter.cs b/src/Components/Components/src/BindConverter.cs index 06a03a05f390..a3e68de026a5 100644 --- a/src/Components/Components/src/BindConverter.cs +++ b/src/Components/Components/src/BindConverter.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Text; using System.Text.Json; +using Microsoft.AspNetCore.Components.HotReload; namespace Microsoft.AspNetCore.Components; @@ -1667,6 +1668,14 @@ private static class FormatterDelegateCache { private static readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); + static FormatterDelegateCache() + { + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += _cache.Clear; + } + } + private static MethodInfo? _makeArrayFormatter; [UnconditionalSuppressMessage( @@ -1856,6 +1865,14 @@ internal static class ParserDelegateCache { private static readonly ConcurrentDictionary _cache = new ConcurrentDictionary(); + static ParserDelegateCache() + { + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += _cache.Clear; + } + } + private static MethodInfo? _convertToEnum; private static MethodInfo? _convertToNullableEnum; private static MethodInfo? _makeArrayTypeConverter; diff --git a/src/Components/Components/src/ComponentFactory.cs b/src/Components/Components/src/ComponentFactory.cs index 12ad8ba03dea..5a6c5b5c71c8 100644 --- a/src/Components/Components/src/ComponentFactory.cs +++ b/src/Components/Components/src/ComponentFactory.cs @@ -4,6 +4,7 @@ using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using System.Reflection; +using Microsoft.AspNetCore.Components.HotReload; using Microsoft.AspNetCore.Components.Reflection; using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.Extensions.DependencyInjection; @@ -18,6 +19,14 @@ private const BindingFlags _injectablePropertyBindingFlags private static readonly ConcurrentDictionary _cachedComponentTypeInfo = new(); + static ComponentFactory() + { + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += ClearCache; + } + } + private readonly IComponentActivator _componentActivator; private readonly Renderer _renderer; diff --git a/src/Components/Components/src/DefaultComponentActivator.cs b/src/Components/Components/src/DefaultComponentActivator.cs index 716591e4a660..24b92dcb1056 100644 --- a/src/Components/Components/src/DefaultComponentActivator.cs +++ b/src/Components/Components/src/DefaultComponentActivator.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Components.HotReload; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Components; @@ -11,6 +12,14 @@ internal sealed class DefaultComponentActivator(IServiceProvider serviceProvider { private static readonly ConcurrentDictionary _cachedComponentTypeInfo = new(); + static DefaultComponentActivator() + { + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += ClearCache; + } + } + public static void ClearCache() => _cachedComponentTypeInfo.Clear(); /// diff --git a/src/Components/Components/src/PersistentState/PersistentServicesRegistry.cs b/src/Components/Components/src/PersistentState/PersistentServicesRegistry.cs index 04310877e9dc..b072cd4c2c88 100644 --- a/src/Components/Components/src/PersistentState/PersistentServicesRegistry.cs +++ b/src/Components/Components/src/PersistentState/PersistentServicesRegistry.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Security.Cryptography; using System.Text; +using Microsoft.AspNetCore.Components.HotReload; using Microsoft.AspNetCore.Components.Reflection; using Microsoft.AspNetCore.Internal; using Microsoft.Extensions.DependencyInjection; @@ -24,6 +25,14 @@ internal sealed class PersistentServicesRegistry private List _subscriptions = []; private static readonly ConcurrentDictionary _cachedAccessorsByType = new(); + static PersistentServicesRegistry() + { + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += _cachedAccessorsByType.Clear; + } + } + public PersistentServicesRegistry(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; diff --git a/src/Components/Components/src/PersistentStateValueProvider.cs b/src/Components/Components/src/PersistentStateValueProvider.cs index 6fd758f38ba4..18589473d4e3 100644 --- a/src/Components/Components/src/PersistentStateValueProvider.cs +++ b/src/Components/Components/src/PersistentStateValueProvider.cs @@ -9,6 +9,7 @@ using System.Reflection; using System.Security.Cryptography; using System.Text; +using Microsoft.AspNetCore.Components.HotReload; using Microsoft.AspNetCore.Components.Reflection; using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Internal; @@ -21,6 +22,20 @@ internal sealed class PersistentStateValueProvider(PersistentComponentState stat private static readonly ConcurrentDictionary<(Type, string), PropertyGetter> _propertyGetterCache = new(); private static readonly ConcurrentDictionary _serializerCache = new(); + static PersistentStateValueProvider() + { + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += ClearCaches; + } + } + + private static void ClearCaches() + { + _propertyGetterCache.Clear(); + _serializerCache.Clear(); + } + private readonly Dictionary _subscriptions = []; public bool IsFixed => false; diff --git a/src/Components/Components/src/Reflection/ComponentProperties.cs b/src/Components/Components/src/Reflection/ComponentProperties.cs index b9e3779c43a0..353576925963 100644 --- a/src/Components/Components/src/Reflection/ComponentProperties.cs +++ b/src/Components/Components/src/Reflection/ComponentProperties.cs @@ -5,12 +5,21 @@ 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 diff --git a/src/Components/Components/src/RenderTree/EventArgsTypeCache.cs b/src/Components/Components/src/RenderTree/EventArgsTypeCache.cs index 1c3a795d9e25..5b9abafb0bed 100644 --- a/src/Components/Components/src/RenderTree/EventArgsTypeCache.cs +++ b/src/Components/Components/src/RenderTree/EventArgsTypeCache.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Reflection; +using Microsoft.AspNetCore.Components.HotReload; namespace Microsoft.AspNetCore.Components.RenderTree; @@ -10,6 +11,14 @@ internal static class EventArgsTypeCache { private static readonly ConcurrentDictionary Cache = new ConcurrentDictionary(); + static EventArgsTypeCache() + { + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += Cache.Clear; + } + } + public static Type GetEventArgsType(MethodInfo methodInfo) { return Cache.GetOrAdd(methodInfo, methodInfo => diff --git a/src/Components/Components/src/Routing/RouteTable.cs b/src/Components/Components/src/Routing/RouteTable.cs index 2d4c9335cc87..f56beec826b9 100644 --- a/src/Components/Components/src/Routing/RouteTable.cs +++ b/src/Components/Components/src/Routing/RouteTable.cs @@ -4,6 +4,7 @@ using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using Microsoft.AspNetCore.Components.HotReload; using Microsoft.AspNetCore.Routing.Tree; namespace Microsoft.AspNetCore.Components.Routing; @@ -13,6 +14,14 @@ internal sealed class RouteTable(TreeRouter treeRouter) private readonly TreeRouter _router = treeRouter; private static readonly ConcurrentDictionary<(Type, string), InboundRouteEntry> _routeEntryCache = new(); + static RouteTable() + { + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += _routeEntryCache.Clear; + } + } + public TreeRouter? TreeRouter => _router; [UnconditionalSuppressMessage( diff --git a/src/Components/Endpoints/src/Microsoft.AspNetCore.Components.Endpoints.csproj b/src/Components/Endpoints/src/Microsoft.AspNetCore.Components.Endpoints.csproj index 40ad0ccab23a..de0329c94e63 100644 --- a/src/Components/Endpoints/src/Microsoft.AspNetCore.Components.Endpoints.csproj +++ b/src/Components/Endpoints/src/Microsoft.AspNetCore.Components.Endpoints.csproj @@ -34,6 +34,7 @@ + diff --git a/src/Components/Endpoints/src/Rendering/EndpointComponentState.cs b/src/Components/Endpoints/src/Rendering/EndpointComponentState.cs index 00a7dfdf7968..6c03d0585f2f 100644 --- a/src/Components/Endpoints/src/Rendering/EndpointComponentState.cs +++ b/src/Components/Endpoints/src/Rendering/EndpointComponentState.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Reflection.Metadata; using Microsoft.AspNetCore.Components.Endpoints; +using Microsoft.AspNetCore.Components.HotReload; using Microsoft.AspNetCore.Components.Rendering; using Microsoft.AspNetCore.Components.RenderTree; @@ -15,6 +16,15 @@ namespace Microsoft.AspNetCore.Components.Endpoints; internal sealed class EndpointComponentState : ComponentState { private static readonly ConcurrentDictionary _streamRenderingAttributeByComponentType = new(); + + static EndpointComponentState() + { + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += _streamRenderingAttributeByComponentType.Clear; + } + } + private readonly EndpointHtmlRenderer _renderer; public EndpointComponentState(Renderer renderer, int componentId, IComponent component, ComponentState? parentComponentState) : base(renderer, componentId, component, parentComponentState) diff --git a/src/Components/Forms/src/FieldIdentifier.cs b/src/Components/Forms/src/FieldIdentifier.cs index 1ff67d80c610..5764b018e4ce 100644 --- a/src/Components/Forms/src/FieldIdentifier.cs +++ b/src/Components/Forms/src/FieldIdentifier.cs @@ -20,7 +20,10 @@ namespace Microsoft.AspNetCore.Components.Forms; static FieldIdentifier() { - HotReloadManager.Default.OnDeltaApplied += ClearCache; + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += ClearCache; + } } /// diff --git a/src/Components/Shared/src/ExpressionFormatting/ExpressionFormatter.cs b/src/Components/Shared/src/ExpressionFormatting/ExpressionFormatter.cs index 73eea91e128d..fa2febd3754e 100644 --- a/src/Components/Shared/src/ExpressionFormatting/ExpressionFormatter.cs +++ b/src/Components/Shared/src/ExpressionFormatting/ExpressionFormatter.cs @@ -14,7 +14,10 @@ internal static class ExpressionFormatter { static ExpressionFormatter() { - HotReloadManager.Default.OnDeltaApplied += ClearCache; + if (HotReloadManager.Default.MetadataUpdateSupported) + { + HotReloadManager.Default.OnDeltaApplied += ClearCache; + } } internal const int StackAllocBufferSize = 128;