| File: RenderHandle.cs | Web Access |
| Project: src\aspnetcore\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.HotReload; using Microsoft.AspNetCore.Components.RenderTree; namespace Microsoft.AspNetCore.Components; /// <summary> /// Allows a component to interact with its renderer. /// </summary> public readonly struct RenderHandle { private readonly Renderer? _renderer; private readonly int _componentId; internal RenderHandle(Renderer renderer, int componentId) { _renderer = renderer ?? throw new ArgumentNullException(nameof(renderer)); _componentId = componentId; } internal ComponentsMetrics? ComponentMetrics => _renderer?.ComponentMetrics; internal ComponentsActivitySource? ComponentActivitySource => _renderer?.ComponentActivitySource; /// <summary> /// Gets the <see cref="Components.Dispatcher" /> associated with the component. /// </summary> public Dispatcher Dispatcher { get { if (_renderer == null) { ThrowNotInitialized(); } return _renderer.Dispatcher; } } /// <summary> /// Gets a value that indicates whether the <see cref="RenderHandle"/> has been /// initialized and is ready to use. /// </summary> public bool IsInitialized => _renderer is not null; /// <summary> /// Gets a value that determines if the <see cref="Renderer"/> is triggering a render in response to a metadata update (hot-reload) change. /// </summary> public bool IsRenderingOnMetadataUpdate => HotReloadManager.IsSupported && (_renderer?.IsRenderingOnMetadataUpdate ?? false); internal bool IsFirstHotReloadRender() => IsRenderingOnMetadataUpdate && _renderer?.IsFirstHotReloadRender(_componentId) == true; internal bool IsRendererDisposed => _renderer?.Disposed ?? throw new InvalidOperationException("No renderer has been initialized."); /// <summary> /// Gets the <see cref="Components.RendererInfo"/> the component is running on. /// </summary> public RendererInfo RendererInfo => _renderer?.RendererInfo ?? throw new InvalidOperationException("No renderer has been initialized."); /// <summary> /// Retrieves the <see cref="IComponentRenderMode"/> assigned to the component. /// </summary> /// <returns>The <see cref="IComponentRenderMode"/> assigned to the component.</returns> public IComponentRenderMode? RenderMode { get { if (_renderer == null) { throw new InvalidOperationException("No renderer has been initialized."); } return _renderer.GetComponentRenderMode(_componentId); } } /// <summary> /// Gets the <see cref="ResourceAssetCollection"/> associated with the <see cref="Renderer"/>. /// </summary> public ResourceAssetCollection Assets { get { return _renderer?.Assets ?? throw new InvalidOperationException("No renderer has been initialized."); } } /// <summary> /// Notifies the renderer that the component should be rendered. /// </summary> /// <param name="renderFragment">The content that should be rendered.</param> public void Render(RenderFragment renderFragment) { if (_renderer == null) { ThrowNotInitialized(); } _renderer.AddToRenderQueue(_componentId, renderFragment); } /// <summary> /// Dispatches an <see cref="Exception"/> to the <see cref="Renderer"/>. /// </summary> /// <param name="exception">The <see cref="Exception"/> that will be dispatched to the renderer.</param> /// <returns>A <see cref="Task"/> that will be completed when the exception has finished dispatching.</returns> public Task DispatchExceptionAsync(Exception exception) { var renderer = _renderer; var componentId = _componentId; return Dispatcher.InvokeAsync(() => renderer!.HandleComponentException(exception, componentId)); } [DoesNotReturn] private static void ThrowNotInitialized() { throw new InvalidOperationException("The render handle is not yet assigned."); } }