Skip to content

Commit 2ef98cd

Browse files
committed
Unify RootComponentTypeCache and PersistentServiceTypeCache
1 parent afabecd commit 2ef98cd

20 files changed

+48
-125
lines changed

src/Components/Components/src/Microsoft.AspNetCore.Components.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
<Compile Include="$(ComponentsSharedSourceRoot)src\ArrayBuilder.cs" LinkBase="RenderTree" />
1818
<Compile Include="$(ComponentsSharedSourceRoot)src\JsonSerializerOptionsProvider.cs" />
1919
<Compile Include="$(ComponentsSharedSourceRoot)src\HotReloadManager.cs" LinkBase="HotReload" />
20+
<Compile Include="$(ComponentsSharedSourceRoot)src\RootTypeCache.cs" LinkBase="Shared" />
2021
<Compile Include="$(SharedSourceRoot)LinkerFlags.cs" LinkBase="Shared" />
2122
<Compile Include="$(SharedSourceRoot)QueryStringEnumerable.cs" LinkBase="Shared" />
2223
<Compile Include="$(SharedSourceRoot)Debugger\DictionaryItemDebugView.cs" LinkBase="Shared" />

src/Components/Components/src/PersistentState/IPersistentComponentRegistration.cs renamed to src/Components/Components/src/PersistentState/IPersistentServiceRegistration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
namespace Microsoft.AspNetCore.Components;
55

66
// Represents a component that is registered for state persistence.
7-
internal interface IPersistentComponentRegistration
7+
internal interface IPersistentServiceRegistration
88
{
99
public string Assembly { get; }
1010
public string FullTypeName { get; }

src/Components/Components/src/PersistentState/PersistentComponentRegistration.cs renamed to src/Components/Components/src/PersistentState/PersistentServiceRegistration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace Microsoft.AspNetCore.Components;
77

88
[DebuggerDisplay($"{{{nameof(GetDebuggerDisplay)}(),nq}}")]
9-
internal sealed class PersistentComponentRegistration<TService>(IComponentRenderMode componentRenderMode) : IPersistentComponentRegistration
9+
internal sealed class PersistentServiceRegistration<TService>(IComponentRenderMode componentRenderMode) : IPersistentServiceRegistration
1010
{
1111
public string Assembly => typeof(TService).Assembly.GetName().Name!;
1212
public string FullTypeName => typeof(TService).FullName!;

src/Components/Components/src/PersistentState/PersistentServiceTypeCache.cs

Lines changed: 0 additions & 82 deletions
This file was deleted.

src/Components/Components/src/PersistentState/PersistentServicesRegistry.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,23 @@ namespace Microsoft.AspNetCore.Components.Infrastructure;
1717
internal sealed class PersistentServicesRegistry
1818
{
1919
private static readonly string _registryKey = typeof(PersistentServicesRegistry).FullName!;
20+
private static readonly RootTypeCache _persistentServiceTypeCache = new RootTypeCache();
2021

2122
private readonly IServiceProvider _serviceProvider;
22-
private readonly PersistentServiceTypeCache _persistentServiceTypeCache;
23-
private IPersistentComponentRegistration[] _registrations;
23+
private IPersistentServiceRegistration[] _registrations;
2424
private List<PersistingComponentStateSubscription> _subscriptions = [];
2525
private static readonly ConcurrentDictionary<Type, PropertiesAccessor> _cachedAccessorsByType = new();
2626

2727
public PersistentServicesRegistry(IServiceProvider serviceProvider)
2828
{
29-
var registrations = serviceProvider.GetRequiredService<IEnumerable<IPersistentComponentRegistration>>();
29+
var registrations = serviceProvider.GetRequiredService<IEnumerable<IPersistentServiceRegistration>>();
3030
_serviceProvider = serviceProvider;
31-
_persistentServiceTypeCache = new PersistentServiceTypeCache();
3231
_registrations = ResolveRegistrations(registrations);
3332
}
3433

3534
internal IComponentRenderMode? RenderMode { get; set; }
3635

37-
internal IReadOnlyList<IPersistentComponentRegistration> Registrations => _registrations;
36+
internal IReadOnlyList<IPersistentServiceRegistration> Registrations => _registrations;
3837

3938
[UnconditionalSuppressMessage(
4039
"Trimming",
@@ -97,10 +96,10 @@ private static void PersistInstanceState(object instance, Type type, PersistentC
9796
[UnconditionalSuppressMessage("Trimming",
9897
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
9998
Justification = "Types registered for persistence are preserved in the API call to register them and typically live in assemblies that aren't trimmed.")]
100-
[DynamicDependency(LinkerFlags.JsonSerialized, typeof(PersistentComponentRegistration))]
99+
[DynamicDependency(LinkerFlags.JsonSerialized, typeof(PersistentServiceRegistration))]
101100
internal void Restore(PersistentComponentState state)
102101
{
103-
if (state.TryTakeFromJson<PersistentComponentRegistration[]>(_registryKey, out var registry) && registry != null)
102+
if (state.TryTakeFromJson<PersistentServiceRegistration[]>(_registryKey, out var registry) && registry != null)
104103
{
105104
_registrations = ResolveRegistrations(_registrations.Concat(registry));
106105
}
@@ -141,9 +140,10 @@ private static void RestoreInstanceState(object instance, Type type, PersistentC
141140
}
142141
}
143142

144-
private static IPersistentComponentRegistration[] ResolveRegistrations(IEnumerable<IPersistentComponentRegistration> registrations) => [.. registrations.DistinctBy(r => (r.Assembly, r.FullTypeName)).OrderBy(r => r.Assembly).ThenBy(r => r.FullTypeName)];
143+
private static IPersistentServiceRegistration[] ResolveRegistrations(IEnumerable<IPersistentServiceRegistration> registrations) => [.. registrations.DistinctBy(r => (r.Assembly, r.FullTypeName)).OrderBy(r => r.Assembly).ThenBy(r => r.FullTypeName)];
145144

146-
private Type? ResolveType(string assembly, string fullTypeName) => _persistentServiceTypeCache.GetPersistentService(assembly, fullTypeName);
145+
private static Type? ResolveType(string assembly, string fullTypeName) =>
146+
_persistentServiceTypeCache.GetRootType(assembly, fullTypeName);
147147

148148
private sealed class PropertiesAccessor
149149
{
@@ -217,7 +217,7 @@ internal static IEnumerable<PropertyInfo> GetCandidateBindableProperties(
217217
}
218218

219219
[DebuggerDisplay($"{{{nameof(GetDebuggerDisplay)}(),nq}}")]
220-
private class PersistentComponentRegistration : IPersistentComponentRegistration
220+
private class PersistentServiceRegistration : IPersistentServiceRegistration
221221
{
222222
public string Assembly { get; set; } = "";
223223

src/Components/Components/src/RenderTree/Renderer.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ protected internal void RemoveRootComponent(int componentId)
316316
/// </summary>
317317
/// <param name="componentId">The root component ID.</param>
318318
/// <returns>The type of the component.</returns>
319-
internal Type GetRootComponentType(int componentId)
319+
internal Type GetRootTypeType(int componentId)
320320
=> GetRequiredRootComponentState(componentId).Component.GetType();
321321

322322
/// <summary>
@@ -1130,9 +1130,9 @@ private void HandleExceptionViaErrorBoundary(Exception error, ComponentState? er
11301130
/// <param name="disposing"><see langword="true"/> if this method is being invoked by <see cref="IDisposable.Dispose"/>, otherwise <see langword="false"/>.</param>
11311131
protected virtual void Dispose(bool disposing)
11321132
{
1133-
// Unlike other Renderer APIs, we need Dispose to be thread-safe
1134-
// (and not require being called only from the sync context)
1135-
// because other classes many need to dispose a Renderer during their own Dispose (rather than DisposeAsync)
1133+
// Unlike other Renderer APIs, we need Dispose to be thread-safe
1134+
// (and not require being called only from the sync context)
1135+
// because other classes many need to dispose a Renderer during their own Dispose (rather than DisposeAsync)
11361136
// and we don't want to force that other code to deal with calling InvokeAsync from a synchronous method.
11371137
lock (_lockObject)
11381138
{

src/Components/Components/src/SupplyParameterFromPersistentComponentStateProviderServiceCollectionExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public static IServiceCollection AddSupplyValueFromPersistentComponentStateProvi
4646
// We look for the type inside the assembly.
4747
// We resolve the service from the DI container.
4848
// We loop through the properties in the type and try to restore the properties that have SupplyParameterFromPersistentComponentState on them.
49-
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPersistentComponentRegistration>(new PersistentComponentRegistration<TService>(componentRenderMode)));
49+
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPersistentServiceRegistration>(new PersistentServiceRegistration<TService>(componentRenderMode)));
5050

5151
return services;
5252
}

src/Components/Components/test/PersistentState/ComponentStatePersistenceManagerTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ private class TestRenderMode : IComponentRenderMode
422422
{
423423
}
424424

425-
private class PersistentService : IPersistentComponentRegistration
425+
private class PersistentService : IPersistentServiceRegistration
426426
{
427427
public string Assembly { get; set; }
428428

src/Components/Components/test/PersistentState/PersistentServicesRegistryTest.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ public async Task PersistStateAsync_DoesNotThrow_WhenTypeCantBeFoundForPersisted
230230
// Arrange
231231
var componentRenderMode = new TestRenderMode();
232232
var serviceProviderOne = new ServiceCollection()
233-
.AddSingleton<IPersistentComponentRegistration>(new TestPersistentRegistration { Assembly = "FakeAssembly", FullTypeName = "FakeType" })
233+
.AddSingleton<IPersistentServiceRegistration>(new TestPersistentRegistration { Assembly = "FakeAssembly", FullTypeName = "FakeType" })
234234
.BuildServiceProvider();
235235

236236
var serviceProviderTwo = new ServiceCollection()
@@ -260,9 +260,9 @@ public void ResolveRegistrations_RemovesDuplicateRegistrations()
260260
{
261261
// Arrange
262262
var serviceProvider = new ServiceCollection()
263-
.AddSingleton<IPersistentComponentRegistration>(new TestPersistentRegistration { Assembly = "Assembly1", FullTypeName = "Type1" })
264-
.AddSingleton<IPersistentComponentRegistration>(new TestPersistentRegistration { Assembly = "Assembly1", FullTypeName = "Type1" }) // Duplicate
265-
.AddSingleton<IPersistentComponentRegistration>(new TestPersistentRegistration { Assembly = "Assembly2", FullTypeName = "Type2" })
263+
.AddSingleton<IPersistentServiceRegistration>(new TestPersistentRegistration { Assembly = "Assembly1", FullTypeName = "Type1" })
264+
.AddSingleton<IPersistentServiceRegistration>(new TestPersistentRegistration { Assembly = "Assembly1", FullTypeName = "Type1" }) // Duplicate
265+
.AddSingleton<IPersistentServiceRegistration>(new TestPersistentRegistration { Assembly = "Assembly2", FullTypeName = "Type2" })
266266
.BuildServiceProvider();
267267

268268
var registry = new PersistentServicesRegistry(serviceProvider);
@@ -490,7 +490,7 @@ private class DerivedService : BaseServiceWithProperty
490490
{
491491
}
492492

493-
private class TestPersistentRegistration : IPersistentComponentRegistration
493+
private class TestPersistentRegistration : IPersistentServiceRegistration
494494
{
495495
public string Assembly { get; set; }
496496
public string FullTypeName { get; set; }

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ internal sealed partial class ServerComponentDeserializer : IServerComponentDese
5959
{
6060
private readonly IDataProtector _dataProtector;
6161
private readonly ILogger<ServerComponentDeserializer> _logger;
62-
private readonly RootComponentTypeCache _rootComponentTypeCache;
62+
private readonly RootTypeCache _RootTypeCache;
6363
private readonly ComponentParameterDeserializer _parametersDeserializer;
6464

6565
// The following fields are only used in TryDeserializeSingleComponentDescriptor.
@@ -72,7 +72,7 @@ internal sealed partial class ServerComponentDeserializer : IServerComponentDese
7272
public ServerComponentDeserializer(
7373
IDataProtectionProvider dataProtectionProvider,
7474
ILogger<ServerComponentDeserializer> logger,
75-
RootComponentTypeCache rootComponentTypeCache,
75+
RootTypeCache RootTypeCache,
7676
ComponentParameterDeserializer parametersDeserializer)
7777
{
7878
// When we protect the data we use a time-limited data protector with the
@@ -87,7 +87,7 @@ public ServerComponentDeserializer(
8787
.ToTimeLimitedDataProtector();
8888

8989
_logger = logger;
90-
_rootComponentTypeCache = rootComponentTypeCache;
90+
_RootTypeCache = RootTypeCache;
9191
_parametersDeserializer = parametersDeserializer;
9292
}
9393

@@ -206,8 +206,8 @@ public bool TryDeserializeWebRootComponentDescriptor(ComponentMarker record, [No
206206
private bool TryDeserializeComponentTypeAndParameters(ServerComponent serverComponent, [NotNullWhen(true)] out Type? componentType, out ParameterView parameters)
207207
{
208208
parameters = default;
209-
componentType = _rootComponentTypeCache
210-
.GetRootComponent(serverComponent.AssemblyName, serverComponent.TypeName);
209+
componentType = _RootTypeCache
210+
.GetRootType(serverComponent.AssemblyName, serverComponent.TypeName);
211211

212212
if (componentType == null)
213213
{

0 commit comments

Comments
 (0)