File: PersistentState\PersistentStateValueProvider.cs
Web Access
Project: src\src\Components\Components\src\Microsoft.AspNetCore.Components.csproj (Microsoft.AspNetCore.Components)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.Extensions.Logging;
 
namespace Microsoft.AspNetCore.Components.Infrastructure;
 
internal sealed partial class PersistentStateValueProvider(PersistentComponentState state, ILogger<PersistentStateValueProvider> logger, IServiceProvider serviceProvider) : ICascadingValueSupplier
{
    private readonly Dictionary<ComponentSubscriptionKey, PersistentValueProviderComponentSubscription> _subscriptions = [];
 
    public bool IsFixed => false;
    // For testing purposes only
    internal Dictionary<ComponentSubscriptionKey, PersistentValueProviderComponentSubscription> Subscriptions => _subscriptions;
 
    public bool CanSupplyValue(in CascadingParameterInfo parameterInfo)
        => parameterInfo.Attribute is PersistentStateAttribute;
 
    [UnconditionalSuppressMessage(
        "ReflectionAnalysis",
        "IL2026:RequiresUnreferencedCode message",
        Justification = "JSON serialization and deserialization might require types that cannot be statically analyzed.")]
    [UnconditionalSuppressMessage(
        "Trimming",
        "IL2072:Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The return value of the source method does not have matching annotations.",
        Justification = "JSON serialization and deserialization might require types that cannot be statically analyzed.")]
    public object? GetCurrentValue(object? key, in CascadingParameterInfo parameterInfo)
    {
        var componentState = (ComponentState)key!;
 
        if (_subscriptions.TryGetValue(new(componentState, parameterInfo.PropertyName), out var subscription))
        {
            return subscription.GetOrComputeLastValue();
        }
 
        return null;
    }
 
    public void Subscribe(ComponentState subscriber, in CascadingParameterInfo parameterInfo)
    {
        var propertyName = parameterInfo.PropertyName;
 
        var componentSubscription = new PersistentValueProviderComponentSubscription(
            state,
            subscriber,
            parameterInfo,
            serviceProvider,
            logger);
 
        _subscriptions.Add(new ComponentSubscriptionKey(subscriber, propertyName), componentSubscription);
    }
 
    public void Unsubscribe(ComponentState subscriber, in CascadingParameterInfo parameterInfo)
    {
        if (_subscriptions.TryGetValue(new(subscriber, parameterInfo.PropertyName), out var subscription))
        {
            subscription.Dispose();
            _subscriptions.Remove(new(subscriber, parameterInfo.PropertyName));
        }
    }
}