< Summary

Information
Class: TeleFlow.Telegram.Internal.Handlers.TelegramErrorHandlerInvoker
Assembly: TeleFlow.Framework
File(s): /_/src/TeleFlow.Framework/Internal/Handlers/TelegramErrorHandlerInvoker.cs
Line coverage
69%
Covered lines: 52
Uncovered lines: 23
Coverable lines: 75
Total lines: 167
Line coverage: 69.3%
Branch coverage
65%
Covered branches: 28
Total branches: 43
Branch coverage: 65.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
InvokeAsync()84.21%221980%
GetTelegramContext(...)50%3250%
GetException(...)50%3250%
GetRouteValue(...)37.5%661642.1%
ValidateResult(...)100%44100%
GetDisplayName(...)100%11100%

File(s)

/_/src/TeleFlow.Framework/Internal/Handlers/TelegramErrorHandlerInvoker.cs

#LineLine coverage
 1using System.Reflection;
 2using System.Runtime.ExceptionServices;
 3using Microsoft.Extensions.DependencyInjection;
 4
 5namespace TeleFlow.Telegram.Internal.Handlers;
 6
 7internal static class TelegramErrorHandlerInvoker
 8{
 9    public static async ValueTask<TelegramErrorHandlingResult> InvokeAsync(
 10        TelegramErrorHandlerDescriptor handler,
 11        TelegramErrorContext errorContext,
 12        TelegramUpdateContext telegramContext,
 13        Exception exception,
 14        IReadOnlyDictionary<string, object?> routeValues,
 15        CancellationToken cancellationToken)
 16    {
 2217        ArgumentNullException.ThrowIfNull(handler);
 2218        ArgumentNullException.ThrowIfNull(errorContext);
 2219        ArgumentNullException.ThrowIfNull(telegramContext);
 2220        ArgumentNullException.ThrowIfNull(exception);
 2221        ArgumentNullException.ThrowIfNull(routeValues);
 22
 2223        var arguments = new object?[handler.Parameters.Count];
 24
 15625        for (var index = 0; index < handler.Parameters.Count; index++)
 26        {
 5627            var parameter = handler.Parameters[index];
 28
 5629            arguments[index] = parameter.Kind switch
 5630            {
 531                TelegramErrorHandlerParameterKind.ErrorContext => errorContext,
 532                TelegramErrorHandlerParameterKind.TelegramContext => GetTelegramContext(handler, parameter, telegramCont
 2233                TelegramErrorHandlerParameterKind.Exception => GetException(handler, parameter, exception),
 234                TelegramErrorHandlerParameterKind.RouteValue => GetRouteValue(handler, parameter, routeValues),
 1935                TelegramErrorHandlerParameterKind.Service => telegramContext.Services.GetRequiredService(parameter.Param
 336                TelegramErrorHandlerParameterKind.CancellationToken => cancellationToken,
 037                _ => throw new InvalidOperationException($"Unsupported error handler parameter kind '{parameter.Kind}'."
 5638            };
 39        }
 40
 2241        if (handler.GeneratedInvoker is not null)
 42        {
 443            return ValidateResult(
 444                handler,
 445                await handler.GeneratedInvoker(telegramContext.Services, arguments, cancellationToken).ConfigureAwait(fa
 46        }
 47
 1848        if (handler.Method is null)
 49        {
 050            throw new InvalidOperationException(
 051                $"Telegram error handler '{GetDisplayName(handler)}' has no invoker.");
 52        }
 53
 1854        var handlerInstance = telegramContext.Services.GetRequiredService(handler.HandlerType);
 55        object? result;
 56
 57        try
 58        {
 1859            result = handler.Method.Invoke(handlerInstance, arguments);
 1860        }
 061        catch (TargetInvocationException reflectionException) when (reflectionException.InnerException is not null)
 62        {
 063            ExceptionDispatchInfo.Capture(reflectionException.InnerException).Throw();
 064            throw;
 65        }
 66
 1867        return result switch
 1868        {
 1469            TelegramErrorHandlingResult handlingResult => ValidateResult(handler, handlingResult),
 370            Task<TelegramErrorHandlingResult> task => ValidateResult(handler, await task.ConfigureAwait(false)),
 171            ValueTask<TelegramErrorHandlingResult> valueTask => ValidateResult(handler, await valueTask.ConfigureAwait(f
 072            _ => throw new InvalidOperationException(
 073                $"Telegram error handler '{GetDisplayName(handler)}' returned an unsupported result.")
 1874        };
 2175    }
 76
 77    private static TelegramUpdateContext GetTelegramContext(
 78        TelegramErrorHandlerDescriptor handler,
 79        TelegramErrorHandlerParameterDescriptor parameter,
 80        TelegramUpdateContext context)
 81    {
 582        if (!parameter.ParameterType.IsInstanceOfType(context))
 83        {
 084            throw new InvalidOperationException(
 085                $"Telegram error handler '{GetDisplayName(handler)}' requires {parameter.ParameterType.Name}, but the se
 86        }
 87
 588        return context;
 89    }
 90
 91    private static Exception GetException(
 92        TelegramErrorHandlerDescriptor handler,
 93        TelegramErrorHandlerParameterDescriptor parameter,
 94        Exception exception)
 95    {
 2296        if (!parameter.ParameterType.IsInstanceOfType(exception))
 97        {
 098            throw new InvalidOperationException(
 099                $"Telegram error handler '{GetDisplayName(handler)}' requires {parameter.ParameterType.Name}, but the th
 100        }
 101
 22102        return exception;
 103    }
 104
 105    private static object? GetRouteValue(
 106        TelegramErrorHandlerDescriptor handler,
 107        TelegramErrorHandlerParameterDescriptor parameter,
 108        IReadOnlyDictionary<string, object?> routeValues)
 109    {
 2110        if (string.IsNullOrWhiteSpace(parameter.Name))
 111        {
 0112            throw new InvalidOperationException(
 0113                $"Telegram error handler '{GetDisplayName(handler)}' has an unnamed route value parameter.");
 114        }
 115
 2116        if (!routeValues.TryGetValue(parameter.Name, out var value))
 117        {
 0118            throw new InvalidOperationException(
 0119                $"Telegram error handler '{GetDisplayName(handler)}' requires route value '{parameter.Name}', but the fa
 120        }
 121
 2122        if (value is null)
 123        {
 0124            if (parameter.ParameterType.IsValueType && Nullable.GetUnderlyingType(parameter.ParameterType) is null)
 125            {
 0126                throw new InvalidOperationException(
 0127                    $"Telegram error handler '{GetDisplayName(handler)}' route value '{parameter.Name}' is null and cann
 128            }
 129
 0130            return null;
 131        }
 132
 2133        var underlyingParameterType = Nullable.GetUnderlyingType(parameter.ParameterType);
 134
 2135        if (underlyingParameterType is not null &&
 2136            underlyingParameterType.IsInstanceOfType(value))
 137        {
 0138            return value;
 139        }
 140
 2141        if (!parameter.ParameterType.IsInstanceOfType(value))
 142        {
 0143            throw new InvalidOperationException(
 0144                $"Telegram error handler '{GetDisplayName(handler)}' route value '{parameter.Name}' has type {value.GetT
 145        }
 146
 2147        return value;
 148    }
 149
 150    private static TelegramErrorHandlingResult ValidateResult(
 151        TelegramErrorHandlerDescriptor handler,
 152        TelegramErrorHandlingResult result)
 153    {
 22154        return result switch
 22155        {
 18156            TelegramErrorHandlingResult.Handled => result,
 3157            TelegramErrorHandlingResult.Unhandled => result,
 1158            _ => throw new InvalidOperationException(
 1159                $"Telegram error handler '{GetDisplayName(handler)}' returned unsupported error handling result '{result
 22160        };
 161    }
 162
 163    private static string GetDisplayName(TelegramErrorHandlerDescriptor handler)
 164    {
 1165        return $"{handler.HandlerType.FullName}.{handler.MethodName}";
 166    }
 167}