| File: EventCallbackWorkItem.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.Reflection; namespace Microsoft.AspNetCore.Components; /// <summary> /// Wraps a callback delegate associated with an event. /// </summary> public readonly struct EventCallbackWorkItem { /// <summary> /// An empty <see cref="EventCallbackWorkItem"/>. /// </summary> public static readonly EventCallbackWorkItem Empty = new EventCallbackWorkItem(null); private readonly MulticastDelegate? _delegate; /// <summary> /// Creates a new <see cref="EventCallbackWorkItem"/> with the provided <paramref name="delegate"/>. /// </summary> /// <param name="delegate">The callback delegate.</param> public EventCallbackWorkItem(MulticastDelegate? @delegate) { _delegate = @delegate; } /// <summary> /// Invokes the delegate associated with this <see cref="EventCallbackWorkItem"/>. /// </summary> /// <param name="arg">The argument to provide to the delegate. May be <c>null</c>.</param> /// <returns>A <see cref="Task"/> then will complete asynchronously once the delegate has completed.</returns> public Task InvokeAsync(object? arg) { return InvokeAsync<object?>(_delegate, arg); } internal static Task InvokeAsync<T>(MulticastDelegate? @delegate, T arg) { switch (@delegate) { case null: return Task.CompletedTask; case Action action: action.Invoke(); return Task.CompletedTask; case Action<T> actionEventArgs: actionEventArgs.Invoke(arg); return Task.CompletedTask; case Func<Task> func: return func.Invoke(); case Func<T, Task> funcEventArgs: return funcEventArgs.Invoke(arg); default: { try { return @delegate.DynamicInvoke(arg) as Task ?? Task.CompletedTask; } catch (TargetInvocationException e) { // Since we fell into the DynamicInvoke case, any exception will be wrapped // in a TIE. We can expect this to be thrown synchronously, so it's low overhead // to unwrap it. return Task.FromException(e.InnerException!); } } } } }