Skip to content

Commit 3717242

Browse files
committed
Rework part of the public APIs
1 parent 2ef98cd commit 3717242

13 files changed

+118
-43
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
#nullable enable
22
Microsoft.AspNetCore.Components.Infrastructure.ComponentStatePersistenceManager.ComponentStatePersistenceManager(Microsoft.Extensions.Logging.ILogger<Microsoft.AspNetCore.Components.Infrastructure.ComponentStatePersistenceManager!>! logger, System.IServiceProvider! serviceProvider) -> void
33
Microsoft.AspNetCore.Components.Infrastructure.ComponentStatePersistenceManager.SetPlatformRenderMode(Microsoft.AspNetCore.Components.IComponentRenderMode! renderMode) -> void
4+
Microsoft.AspNetCore.Components.Infrastructure.RegisterPersistentComponentStateServiceCollectionExtensions
45
Microsoft.AspNetCore.Components.SupplyParameterFromPersistentComponentStateAttribute
56
Microsoft.AspNetCore.Components.SupplyParameterFromPersistentComponentStateAttribute.SupplyParameterFromPersistentComponentStateAttribute() -> void
67
Microsoft.AspNetCore.Components.SupplyParameterFromPersistentComponentStateProviderServiceCollectionExtensions
8+
Microsoft.Extensions.DependencyInjection.SupplyParameterFromPersistentComponentStateProviderServiceCollectionExtensions
9+
static Microsoft.AspNetCore.Components.Infrastructure.RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration<TService>(Microsoft.Extensions.DependencyInjection.IServiceCollection! services, Microsoft.AspNetCore.Components.IComponentRenderMode! componentRenderMode) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
710
static Microsoft.AspNetCore.Components.SupplyParameterFromPersistentComponentStateProviderServiceCollectionExtensions.AddPersistentService<TService>(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, Microsoft.AspNetCore.Components.IComponentRenderMode! componentRenderMode) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
811
static Microsoft.AspNetCore.Components.SupplyParameterFromPersistentComponentStateProviderServiceCollectionExtensions.AddSupplyValueFromPersistentComponentStateProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
12+
static Microsoft.Extensions.DependencyInjection.SupplyParameterFromPersistentComponentStateProviderServiceCollectionExtensions.AddSupplyValueFromPersistentComponentStateProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Diagnostics.CodeAnalysis;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Microsoft.Extensions.DependencyInjection.Extensions;
7+
using static Microsoft.AspNetCore.Internal.LinkerFlags;
8+
9+
namespace Microsoft.AspNetCore.Components.Infrastructure;
10+
11+
/// <summary>
12+
/// Infrastructure APIs for registering services that persist state.
13+
/// </summary>
14+
public static class RegisterPersistentComponentStateServiceCollectionExtensions
15+
{
16+
/// <summary>
17+
/// Saves <typeparamref name="TService"/> state when the application is persisting state and restores it at the appropriate time automatically.
18+
/// </summary>
19+
/// <remarks>
20+
/// Only public properties annotated with <see cref="SupplyParameterFromPersistentComponentStateAttribute"/> are persisted and restored.
21+
/// </remarks>
22+
/// <typeparam name="TService">The service type to register for persistence.</typeparam>
23+
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
24+
/// <param name="componentRenderMode">The <see cref="IComponentRenderMode"/> to register the service for.</param>
25+
/// <returns>The <see cref="IServiceCollection"/>.</returns>
26+
public static IServiceCollection AddPersistentServiceRegistration<[DynamicallyAccessedMembers(JsonSerialized)] TService>(
27+
IServiceCollection services,
28+
IComponentRenderMode componentRenderMode)
29+
{
30+
// This method does something very similar to what we do when we register root components, except in this case we are registering services.
31+
// We collect a list of all the registrations on during static rendering mode and push those registrations to interactive mode.
32+
// When the interactive mode starts, we retrieve the registry, and this triggers the process for restoring all the states for all the services.
33+
// The process for retrieving the services is the same as we do for root components.
34+
// We look for the assembly in the current list of loaded assemblies.
35+
// We look for the type inside the assembly.
36+
// We resolve the service from the DI container.
37+
// We loop through the properties in the type and try to restore the properties that have SupplyParameterFromPersistentComponentState on them.
38+
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPersistentServiceRegistration>(new PersistentServiceRegistration<TService>(componentRenderMode)));
39+
40+
return services;
41+
}
42+
}
Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Diagnostics.CodeAnalysis;
5-
using Microsoft.Extensions.DependencyInjection;
4+
using Microsoft.AspNetCore.Components;
65
using Microsoft.Extensions.DependencyInjection.Extensions;
7-
using static Microsoft.AspNetCore.Internal.LinkerFlags;
86

9-
namespace Microsoft.AspNetCore.Components;
7+
namespace Microsoft.Extensions.DependencyInjection;
108

119
/// <summary>
1210
/// Enables component parameters to be supplied from <see cref="PersistentComponentState"/> with <see cref="SupplyParameterFromPersistentComponentStateAttribute"/>.
@@ -23,31 +21,4 @@ public static IServiceCollection AddSupplyValueFromPersistentComponentStateProvi
2321
services.TryAddEnumerable(ServiceDescriptor.Scoped<ICascadingValueSupplier, SupplyParameterFromPersistentComponentStateValueProvider>());
2422
return services;
2523
}
26-
27-
/// <summary>
28-
/// Saves <typeparamref name="TService"/> state when the application is persisting state and restores it at the appropriate time automatically.
29-
/// </summary>
30-
/// <remarks>
31-
/// Only public properties annotated with <see cref="SupplyParameterFromPersistentComponentStateAttribute"/> are persisted and restored.
32-
/// </remarks>
33-
/// <typeparam name="TService">The service type to register for persistence.</typeparam>
34-
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
35-
/// <param name="componentRenderMode">The <see cref="IComponentRenderMode"/> to register the service for.</param>
36-
/// <returns>The <see cref="IServiceCollection"/>.</returns>
37-
public static IServiceCollection AddPersistentService<[DynamicallyAccessedMembers(JsonSerialized)] TService>(
38-
this IServiceCollection services,
39-
IComponentRenderMode componentRenderMode)
40-
{
41-
// This method does something very similar to what we do when we register root components, except in this case we are registering services.
42-
// We collect a list of all the registrations on during static rendering mode and push those registrations to interactive mode.
43-
// When the interactive mode starts, we retrieve the registry, and this triggers the process for restoring all the states for all the services.
44-
// The process for retrieving the services is the same as we do for root components.
45-
// We look for the assembly in the current list of loaded assemblies.
46-
// We look for the type inside the assembly.
47-
// We resolve the service from the DI container.
48-
// We loop through the properties in the type and try to restore the properties that have SupplyParameterFromPersistentComponentState on them.
49-
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPersistentServiceRegistration>(new PersistentServiceRegistration<TService>(componentRenderMode)));
50-
51-
return services;
52-
}
5324
}

src/Components/Components/src/SupplyParameterFromPersistentComponentStateValueProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ private static void GrowBuffer(ref byte[]? pool, ref Span<byte> keyBuffer, int?
221221

222222
private static object? GetSerializableKey(ComponentState componentState)
223223
{
224-
if (componentState.LogicalParentComponentState is not { } parentComponentState)
224+
if (componentState.ParentComponentState is not { } parentComponentState)
225225
{
226226
return null;
227227
}
@@ -248,7 +248,7 @@ private static void GrowBuffer(ref byte[]? pool, ref Span<byte> keyBuffer, int?
248248
private static string GetComponentType(ComponentState componentState) => componentState.Component.GetType().FullName!;
249249

250250
private static string GetParentComponentType(ComponentState componentState) =>
251-
componentState.LogicalParentComponentState == null ? "" : GetComponentType(componentState.LogicalParentComponentState);
251+
componentState.ParentComponentState == null ? "" : GetComponentType(componentState.ParentComponentState);
252252

253253
private static byte[] KeyFactory((string parentComponentType, string componentType, string propertyName) parts) =>
254254
SHA256.HashData(Encoding.UTF8.GetBytes(string.Join(".", parts.parentComponentType, parts.componentType, parts.propertyName)));

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,5 +430,15 @@ private class PersistentService : IPersistentServiceRegistration
430430

431431
public IComponentRenderMode GetRenderModeOrDefault() => null;
432432
}
433+
}
433434

435+
static file class ComponentStatePersistenceManagerExtensions
436+
{
437+
public static IServiceCollection AddPersistentService<TPersistentService>(this IServiceCollection services, IComponentRenderMode renderMode)
438+
{
439+
RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration<TPersistentService>(
440+
services,
441+
renderMode);
442+
return services;
443+
}
434444
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,3 +498,15 @@ private class TestPersistentRegistration : IPersistentServiceRegistration
498498
public IComponentRenderMode GetRenderModeOrDefault() => null;
499499
}
500500
}
501+
502+
503+
static file class ComponentStatePersistenceManagerExtensions
504+
{
505+
public static IServiceCollection AddPersistentService<TPersistentService>(this IServiceCollection services, IComponentRenderMode renderMode)
506+
{
507+
RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration<TPersistentService>(
508+
services,
509+
renderMode);
510+
return services;
511+
}
512+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Diagnostics.CodeAnalysis;
5+
using Microsoft.AspNetCore.Components;
6+
using Microsoft.AspNetCore.Components.Infrastructure;
7+
using Microsoft.AspNetCore.Internal;
8+
9+
namespace Microsoft.Extensions.DependencyInjection;
10+
11+
/// <summary>
12+
/// Provides methods for configuring a Razor components based application.
13+
/// </summary>
14+
public static class RazorComponentsRazorComponentBuilderExtensions
15+
{
16+
/// <summary>
17+
/// Registers a persistent service with the specified render mode in the Razor components builder.
18+
/// </summary>
19+
/// <typeparam name="TPersistentService">The service to be registered for state management.</typeparam>
20+
/// <param name="builder">The <see cref="IRazorComponentsBuilder"/>.</param>
21+
/// <param name="renderMode">The <see cref="IComponentRenderMode"/> that determines to which render modes the state should be persisted.</param>
22+
/// <returns>The <see cref="IRazorComponentsBuilder"/>.</returns>
23+
public static IRazorComponentsBuilder RegisterPersistentService<[DynamicallyAccessedMembers(LinkerFlags.JsonSerialized)] TPersistentService>(
24+
this IRazorComponentsBuilder builder,
25+
IComponentRenderMode renderMode)
26+
{
27+
ArgumentNullException.ThrowIfNull(builder);
28+
29+
RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration<TPersistentService>(
30+
builder.Services,
31+
renderMode);
32+
33+
return builder;
34+
}
35+
}

src/Components/Endpoints/src/DependencyInjection/RazorComponentsServiceCollectionExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public static IRazorComponentsBuilder AddRazorComponents(this IServiceCollection
8080
services.AddSupplyValueFromFormProvider();
8181
services.TryAddScoped<AntiforgeryStateProvider, EndpointAntiforgeryStateProvider>();
8282
services.TryAddScoped(sp => (EndpointAntiforgeryStateProvider)sp.GetRequiredService<AntiforgeryStateProvider>());
83-
services.AddPersistentService<AntiforgeryStateProvider>(RenderMode.InteractiveAuto);
83+
RegisterPersistentComponentStateServiceCollectionExtensions.AddPersistentServiceRegistration<AntiforgeryStateProvider>(services, RenderMode.InteractiveAuto);
8484
services.TryAddScoped<HttpContextFormDataProvider>();
8585
services.TryAddScoped<IFormValueMapper, HttpContextFormValueMapper>();
8686

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
#nullable enable
2+
Microsoft.Extensions.DependencyInjection.RazorComponentsRazorComponentBuilderExtensions
3+
static Microsoft.Extensions.DependencyInjection.RazorComponentsRazorComponentBuilderExtensions.RegisterPersistentService<TPersistentService>(this Microsoft.Extensions.DependencyInjection.IRazorComponentsBuilder! builder, Microsoft.AspNetCore.Components.IComponentRenderMode! renderMode) -> Microsoft.Extensions.DependencyInjection.IRazorComponentsBuilder!

src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.PrerenderingState.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ public async ValueTask<IHtmlContent> PrerenderPersistedStateAsync(HttpContext ht
134134
}
135135

136136
var manager = _httpContext.RequestServices.GetRequiredService<ComponentStatePersistenceManager>();
137+
137138
// Now given the mode, we obtain a particular store for that mode
138139
// and persist the state and return the HTML content
139140
switch (serializationMode)

0 commit comments

Comments
 (0)