Skip to content

Commit b2d6288

Browse files
Copilotjaviercn
andcommitted
Make RootTypeCache fields static and add hot reload support in constructors
Co-authored-by: javiercn <6995051+javiercn@users.noreply.github.com>
1 parent 562666c commit b2d6288

File tree

4 files changed

+15
-12
lines changed

4 files changed

+15
-12
lines changed

src/Components/Server/src/Circuits/ServerComponentDeserializer.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Diagnostics.CodeAnalysis;
66
using System.Text;
77
using System.Text.Json;
8+
using Microsoft.AspNetCore.Components.HotReload;
89
using Microsoft.AspNetCore.DataProtection;
910
using Microsoft.Extensions.Logging;
1011

@@ -57,11 +58,19 @@ namespace Microsoft.AspNetCore.Components.Server;
5758
// * If a marker can't be unprotected we will fail early. We know that the marker was tampered with and can't be trusted.
5859
internal sealed partial class ServerComponentDeserializer : IServerComponentDeserializer
5960
{
61+
private static readonly RootTypeCache _rootTypeCache = new();
6062
private readonly IDataProtector _dataProtector;
6163
private readonly ILogger<ServerComponentDeserializer> _logger;
62-
private readonly RootTypeCache _RootTypeCache;
6364
private readonly ComponentParameterDeserializer _parametersDeserializer;
6465

66+
static ServerComponentDeserializer()
67+
{
68+
if (HotReloadManager.Default.MetadataUpdateSupported)
69+
{
70+
HotReloadManager.Default.OnDeltaApplied += _rootTypeCache.Clear;
71+
}
72+
}
73+
6574
// The following fields are only used in TryDeserializeSingleComponentDescriptor.
6675
// The TryDeserializeComponentDescriptorCollection method uses a stateless
6776
// approach to efficiently detect invalid component records.
@@ -72,7 +81,6 @@ internal sealed partial class ServerComponentDeserializer : IServerComponentDese
7281
public ServerComponentDeserializer(
7382
IDataProtectionProvider dataProtectionProvider,
7483
ILogger<ServerComponentDeserializer> logger,
75-
RootTypeCache RootTypeCache,
7684
ComponentParameterDeserializer parametersDeserializer)
7785
{
7886
// When we protect the data we use a time-limited data protector with the
@@ -87,7 +95,6 @@ public ServerComponentDeserializer(
8795
.ToTimeLimitedDataProtector();
8896

8997
_logger = logger;
90-
_RootTypeCache = RootTypeCache;
9198
_parametersDeserializer = parametersDeserializer;
9299
}
93100

@@ -206,7 +213,7 @@ public bool TryDeserializeWebRootComponentDescriptor(ComponentMarker record, [No
206213
private bool TryDeserializeComponentTypeAndParameters(ServerComponent serverComponent, [NotNullWhen(true)] out Type? componentType, out ParameterView parameters)
207214
{
208215
parameters = default;
209-
componentType = _RootTypeCache
216+
componentType = _rootTypeCache
210217
.GetRootType(serverComponent.AssemblyName, serverComponent.TypeName);
211218

212219
if (componentType == null)

src/Components/Server/test/Circuits/ServerComponentDeserializerTest.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,6 @@ private ServerComponentDeserializer CreateServerComponentDeserializer()
436436
return new ServerComponentDeserializer(
437437
_ephemeralDataProtectionProvider,
438438
NullLogger<ServerComponentDeserializer>.Instance,
439-
new RootTypeCache(),
440439
new ComponentParameterDeserializer(NullLogger<ComponentParameterDeserializer>.Instance, new ComponentParametersTypeCache()));
441440
}
442441

src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ public sealed class WebAssemblyHostBuilder
2828
{
2929
private readonly IInternalJSImportMethods _jsMethods;
3030
private Func<IServiceProvider> _createServiceProvider;
31-
private RootTypeCache? _rootComponentCache;
3231
private string? _persistedState;
3332
private ServiceProviderOptions? _serviceProviderOptions;
3433

@@ -146,11 +145,10 @@ private void InitializeRegisteredRootComponents()
146145
registeredComponents[i].PrerenderId = i.ToString(CultureInfo.InvariantCulture);
147146
}
148147

149-
_rootComponentCache = new RootTypeCache();
150148
var componentDeserializer = WebAssemblyComponentParameterDeserializer.Instance;
151149
foreach (var registeredComponent in registeredComponents)
152150
{
153-
var componentType = _rootComponentCache.GetRootType(registeredComponent.Assembly!, registeredComponent.TypeName!);
151+
var componentType = DefaultWebAssemblyJSRuntime._rootComponentCache.GetRootType(registeredComponent.Assembly!, registeredComponent.TypeName!);
154152
if (componentType is null)
155153
{
156154
throw new InvalidOperationException(
@@ -325,8 +323,7 @@ internal void InitializeDefaultServices()
325323
Services.AddSingleton(new LazyAssemblyLoader(DefaultWebAssemblyJSRuntime.Instance));
326324
Services.AddSingleton(serviceProvider =>
327325
{
328-
var cache = _rootComponentCache ?? new RootTypeCache();
329-
return cache;
326+
return new RootTypeCache();
330327
});
331328
Services.AddSingleton<ComponentStatePersistenceManager>();
332329
Services.AddSingleton(sp => sp.GetRequiredService<ComponentStatePersistenceManager>().State);

src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ internal sealed partial class DefaultWebAssemblyJSRuntime : WebAssemblyJSRuntime
2020
{
2121
public static readonly DefaultWebAssemblyJSRuntime Instance = new();
2222

23-
private readonly RootTypeCache _rootComponentCache = new();
23+
internal static readonly RootTypeCache _rootComponentCache = new();
2424

2525
public ElementReferenceContext ElementReferenceContext { get; }
2626

@@ -131,7 +131,7 @@ internal static RootComponentOperationBatch DeserializeOperations(string operati
131131
throw new InvalidOperationException($"The component operation of type '{operation.Type}' requires a '{nameof(operation.Marker)}' to be specified.");
132132
}
133133

134-
var componentType = Instance._rootComponentCache.GetRootType(operation.Marker!.Value.Assembly!, operation.Marker.Value.TypeName!)
134+
var componentType = _rootComponentCache.GetRootType(operation.Marker!.Value.Assembly!, operation.Marker.Value.TypeName!)
135135
?? throw new InvalidOperationException($"Root component type '{operation.Marker.Value.TypeName}' could not be found in the assembly '{operation.Marker.Value.Assembly}'.");
136136
var parameters = DeserializeComponentParameters(operation.Marker.Value);
137137
operation.Descriptor = new(componentType, parameters);

0 commit comments

Comments
 (0)