< Summary

Information
Class: Elsa.Mediator.Extensions.HandlerExtensions
Assembly: Elsa.Mediator
File(s): /home/runner/work/elsa-core/elsa-core/src/common/Elsa.Mediator/Extensions/HandlerExtensions.cs
Line coverage
94%
Covered lines: 17
Uncovered lines: 1
Coverable lines: 18
Total lines: 82
Line coverage: 94.4%
Branch coverage
100%
Covered branches: 6
Total branches: 6
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetNotificationHandlerMethod(...)100%11100%
GetCommandHandlerMethod(...)100%66100%
InvokeAsync(...)100%11100%
InvokeAsync(...)100%11100%
InvokeAndUnwrap(...)100%1180%

File(s)

/home/runner/work/elsa-core/elsa-core/src/common/Elsa.Mediator/Extensions/HandlerExtensions.cs

#LineLine coverage
 1using System.Diagnostics.CodeAnalysis;
 2using System.Reflection;
 3using System.Runtime.ExceptionServices;
 4using Elsa.Mediator.Contracts;
 5using Elsa.Mediator.Middleware.Command;
 6using Elsa.Mediator.Middleware.Notification;
 7using Elsa.Mediator.Models;
 8
 9namespace Elsa.Mediator.Extensions;
 10
 11/// <summary>
 12/// Contains helper methods for invoking notification handlers.
 13/// </summary>
 14public static class HandlerExtensions
 15{
 16    /// <summary>
 17    /// Gets the handle method for a notification handler of the given notification type.
 18    /// </summary>
 19    /// <param name="notificationType">The notification type.</param>
 20    /// <returns>The handle method.</returns>
 21    public static MethodInfo GetNotificationHandlerMethod(this Type notificationType)
 22    {
 1371123        var handlerType = typeof(INotificationHandler<>).MakeGenericType(notificationType);
 1371124        return handlerType.GetMethod("HandleAsync")!;
 25    }
 26
 27    /// <summary>
 28    /// Gets the handle method for a command handler of the given command type.
 29    /// </summary>
 30    /// <param name="commandType">The command type.</param>
 31    /// <returns>The handle method.</returns>
 32    public static MethodInfo GetCommandHandlerMethod([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfac
 33    {
 4134        var commandTypeInterfaces = commandType.GetInterfaces();
 9735        var commandTypeInterface = commandTypeInterfaces.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefiniti
 4136        var resultType = commandTypeInterface?.GetGenericArguments()[0] ?? typeof(Unit);
 4137        var handlerType = typeof(ICommandHandler<,>).MakeGenericType(commandType, resultType);
 4138        return handlerType.GetMethod("HandleAsync")!;
 39    }
 40
 41    /// <summary>
 42    /// Invokes the given handler for the given notification.
 43    /// </summary>
 44    /// <param name="handler">The handler to invoke.</param>
 45    /// <param name="handleMethod">The handle method.</param>
 46    /// <param name="notificationContext">The notification context containing the notification and cancellation token.</
 47    public static Task InvokeAsync(this INotificationHandler handler, MethodBase handleMethod, NotificationContext notif
 48    {
 1687349        var notification = notificationContext.Notification;
 1687350        var cancellationToken = notificationContext.CancellationToken;
 1687351        return InvokeAndUnwrap<Task>(handleMethod, handler, [notification, cancellationToken]);
 52    }
 53
 54    /// <summary>
 55    /// Invokes the given handler for the given command.
 56    /// </summary>
 57    /// <param name="handler">The handler to invoke.</param>
 58    /// <param name="handleMethod">The handle method.</param>
 59    /// <param name="commandContext">The command to handle.</param>
 60    public static Task<TResult> InvokeAsync<TResult>(this ICommandHandler handler, MethodBase handleMethod, CommandConte
 61    {
 4162        var command = commandContext.Command;
 4163        var cancellationToken = commandContext.CancellationToken;
 4164        return InvokeAndUnwrap<Task<TResult>>(handleMethod, handler, [command, cancellationToken]);
 65    }
 66
 67    /// <summary>
 68    /// Invokes a method via reflection and unwraps any TargetInvocationException to preserve the original exception's s
 69    /// </summary>
 70    private static T InvokeAndUnwrap<T>(MethodBase method, object target, object[] args) where T : Task
 71    {
 72        try
 73        {
 1691474            return (T)method.Invoke(target, args)!;
 75        }
 176        catch (TargetInvocationException ex) when (ex.InnerException is not null)
 77        {
 178            ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
 079            throw; // Unreachable, but required for compiler
 80        }
 1691381    }
 82}