| File: EventCallbackOfT.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.Runtime.CompilerServices; namespace Microsoft.AspNetCore.Components; /// <summary> /// A bound event handler delegate. /// </summary> public readonly struct EventCallback<TValue> : IEventCallback { /// <summary> /// Gets an empty <see cref="EventCallback{TValue}"/>. /// </summary> public static readonly EventCallback<TValue> Empty = new EventCallback<TValue>(null, (Action)(() => { })); internal readonly MulticastDelegate? Delegate; internal readonly IHandleEvent? Receiver; /// <summary> /// Creates the new <see cref="EventCallback{TValue}"/>. /// </summary> /// <param name="receiver">The event receiver.</param> /// <param name="delegate">The delegate to bind.</param> public EventCallback(IHandleEvent? receiver, MulticastDelegate? @delegate) { Receiver = receiver; Delegate = @delegate; } /// <summary> /// Gets a value that indicates whether the delegate associated with this event dispatcher is non-null. /// </summary> public bool HasDelegate => Delegate != null; // This is a hint to the runtime that Receiver is a different object than what // Delegate.Target points to. This allows us to avoid boxing the command object // when building the render tree. See logic where this is used. internal bool RequiresExplicitReceiver => Receiver != null && !object.ReferenceEquals(Receiver, Delegate?.Target); /// <summary> /// Invokes the delegate associated with this binding and dispatches an event notification to the /// appropriate component. /// </summary> /// <param name="arg">The argument.</param> /// <returns>A <see cref="Task"/> which completes asynchronously once event processing has completed.</returns> public Task InvokeAsync(TValue? arg) { if (Receiver == null) { return EventCallbackWorkItem.InvokeAsync<TValue?>(Delegate, arg); } return Receiver.HandleEventAsync(new EventCallbackWorkItem(Delegate), arg); } /// <summary> /// Invokes the delegate associated with this binding and dispatches an event notification to the /// appropriate component. /// </summary> /// <returns>A <see cref="Task"/> which completes asynchronously once event processing has completed.</returns> public Task InvokeAsync() => InvokeAsync(default!); internal EventCallback AsUntyped() { return new EventCallback(Receiver ?? Delegate?.Target as IHandleEvent, Delegate); } object? IEventCallback.UnpackForRenderTree() { return RequiresExplicitReceiver ? (object)AsUntyped() : Delegate; } /// <inheritdoc /> public override int GetHashCode() => HashCode.Combine(RuntimeHelpers.GetHashCode(Receiver), RuntimeHelpers.GetHashCode(Delegate)); /// <inheritdoc /> public override bool Equals(object? obj) => obj is EventCallback<TValue> other && ReferenceEquals(Receiver, other.Receiver) && (Delegate?.Equals(other.Delegate) ?? (other.Delegate == null)); }