| File: Window.cs | Web Access |
| Project: Microsoft.AspNetCore.Components.Platform.csproj (Microsoft.AspNetCore.Components.Platform) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Linq; using Microsoft.JSInterop; namespace Microsoft.AspNetCore.Components.Platform; /// <summary> /// Represents the active browser window. /// </summary> public sealed class Window : IInternalAsyncDisposal { private readonly IJSRuntime _jsRuntime; private readonly Dictionary<(Type FeatureType, string? Subkey), object> _features = []; private bool _disposed; internal Window(IJSRuntime jsRuntime) { _jsRuntime = jsRuntime; } /// <summary> /// Gets the projection of type <typeparamref name="T"/>, creating it on first access. /// </summary> /// <typeparam name="T">The projection type.</typeparam> /// <param name="factory">The callback that creates the projection.</param> /// <returns>The projection keyed by <typeparamref name="T"/>.</returns> internal T GetOrAddFeature<T>(Func<IJSRuntime, T> factory) where T : class => GetOrAddFeatureCore(subkey: null, factory); /// <summary> /// Gets the projection of type <typeparamref name="T"/> identified by <paramref name="subkey"/>, /// creating it on first access. /// </summary> /// <remarks> /// Use this overload when multiple projections share the same <typeparamref name="T"/>, such as /// the local and session <see cref="Storage"/> instances. /// </remarks> /// <typeparam name="T">The projection type.</typeparam> /// <param name="subkey">The key that distinguishes this projection from others of the same type.</param> /// <param name="factory">The callback that creates the projection.</param> /// <returns>The projection keyed by <typeparamref name="T"/> and <paramref name="subkey"/>.</returns> internal T GetOrAddFeature<T>(string subkey, Func<IJSRuntime, T> factory) where T : class { ArgumentNullException.ThrowIfNull(subkey); return GetOrAddFeatureCore(subkey, factory); } private T GetOrAddFeatureCore<T>(string? subkey, Func<IJSRuntime, T> factory) where T : class { ArgumentNullException.ThrowIfNull(factory); ObjectDisposedException.ThrowIf(_disposed, this); var key = (typeof(T), subkey); if (_features.TryGetValue(key, out var existing)) { return (T)existing; } var created = factory(_jsRuntime); _features[key] = created; return created; } async ValueTask IInternalAsyncDisposal.InternalDisposeAsync() { if (_disposed) { return; } _disposed = true; var features = _features.Values.ToArray(); _features.Clear(); foreach (var feature in features) { if (feature is IInternalAsyncDisposal disposable) { await disposable.InternalDisposeAsync().ConfigureAwait(false); } } } }