| | | 1 | | using System.Reflection; |
| | | 2 | | using System.Runtime.ExceptionServices; |
| | | 3 | | using Microsoft.Extensions.DependencyInjection; |
| | | 4 | | |
| | | 5 | | namespace TeleFlow.Telegram.Internal.Handlers; |
| | | 6 | | |
| | | 7 | | internal static class TelegramHandlerInvoker |
| | | 8 | | { |
| | | 9 | | public static async Task InvokeAsync( |
| | | 10 | | TelegramRouteSelection selection, |
| | | 11 | | TelegramUpdateContext context, |
| | | 12 | | CancellationToken cancellationToken) |
| | | 13 | | { |
| | 322 | 14 | | ArgumentNullException.ThrowIfNull(selection); |
| | | 15 | | |
| | 322 | 16 | | var handler = selection.Handler; |
| | 322 | 17 | | var arguments = new object?[handler.Parameters.Count]; |
| | | 18 | | |
| | 1964 | 19 | | for (var index = 0; index < handler.Parameters.Count; index++) |
| | | 20 | | { |
| | 661 | 21 | | var parameter = handler.Parameters[index]; |
| | | 22 | | |
| | 661 | 23 | | arguments[index] = parameter.Kind switch |
| | 661 | 24 | | { |
| | 322 | 25 | | TelegramHandlerParameterKind.Context => context, |
| | 9 | 26 | | TelegramHandlerParameterKind.CallbackPayload => selection.CallbackPayload, |
| | 27 | 27 | | TelegramHandlerParameterKind.RouteValue => GetRouteValue(selection, parameter), |
| | 287 | 28 | | TelegramHandlerParameterKind.Service => context.Services.GetRequiredService(parameter.ParameterType), |
| | 16 | 29 | | TelegramHandlerParameterKind.CancellationToken => cancellationToken, |
| | 0 | 30 | | _ => throw new InvalidOperationException($"Unsupported handler parameter kind '{parameter.Kind}'.") |
| | 661 | 31 | | }; |
| | | 32 | | } |
| | | 33 | | |
| | 321 | 34 | | if (handler.GeneratedInvoker is not null) |
| | | 35 | | { |
| | 56 | 36 | | await handler.GeneratedInvoker(context.Services, arguments, cancellationToken).ConfigureAwait(false); |
| | 53 | 37 | | return; |
| | | 38 | | } |
| | | 39 | | |
| | 265 | 40 | | if (handler.Method is null) |
| | | 41 | | { |
| | 0 | 42 | | throw new InvalidOperationException( |
| | 0 | 43 | | $"Telegram handler '{TelegramHandlerDescriptorFormatter.GetDisplayName(handler)}' has no invoker."); |
| | | 44 | | } |
| | | 45 | | |
| | 265 | 46 | | var handlerInstance = context.Services.GetRequiredService(handler.HandlerType); |
| | | 47 | | object? result; |
| | | 48 | | |
| | | 49 | | try |
| | | 50 | | { |
| | 265 | 51 | | result = handler.Method.Invoke(handlerInstance, arguments); |
| | 262 | 52 | | } |
| | 3 | 53 | | catch (TargetInvocationException exception) when (exception.InnerException is not null) |
| | | 54 | | { |
| | 3 | 55 | | ExceptionDispatchInfo.Capture(exception.InnerException).Throw(); |
| | 0 | 56 | | throw; |
| | | 57 | | } |
| | | 58 | | |
| | | 59 | | switch (result) |
| | | 60 | | { |
| | | 61 | | case Task task: |
| | 261 | 62 | | await task.ConfigureAwait(false); |
| | 243 | 63 | | break; |
| | | 64 | | case ValueTask valueTask: |
| | 1 | 65 | | await valueTask.ConfigureAwait(false); |
| | 1 | 66 | | break; |
| | | 67 | | default: |
| | 0 | 68 | | throw new InvalidOperationException( |
| | 0 | 69 | | $"Telegram handler '{TelegramHandlerDescriptorFormatter.GetDisplayName(handler)}' returned an unsupp |
| | | 70 | | } |
| | 297 | 71 | | } |
| | | 72 | | |
| | | 73 | | private static object? GetRouteValue( |
| | | 74 | | TelegramRouteSelection selection, |
| | | 75 | | TelegramHandlerParameterDescriptor parameter) |
| | | 76 | | { |
| | 27 | 77 | | if (string.IsNullOrWhiteSpace(parameter.Name)) |
| | | 78 | | { |
| | 0 | 79 | | throw new InvalidOperationException( |
| | 0 | 80 | | $"Telegram handler '{TelegramHandlerDescriptorFormatter.GetDisplayName(selection.Handler)}' has an unnam |
| | | 81 | | } |
| | | 82 | | |
| | 27 | 83 | | if (!selection.RouteValues.TryGetValue(parameter.Name, out var value)) |
| | | 84 | | { |
| | 1 | 85 | | throw new InvalidOperationException( |
| | 1 | 86 | | $"Telegram handler '{TelegramHandlerDescriptorFormatter.GetDisplayName(selection.Handler)}' requires rou |
| | | 87 | | } |
| | | 88 | | |
| | 26 | 89 | | if (value is null) |
| | | 90 | | { |
| | 3 | 91 | | if (parameter.ParameterType.IsValueType && Nullable.GetUnderlyingType(parameter.ParameterType) is null) |
| | | 92 | | { |
| | 0 | 93 | | throw new InvalidOperationException( |
| | 0 | 94 | | $"Telegram handler '{TelegramHandlerDescriptorFormatter.GetDisplayName(selection.Handler)}' route va |
| | | 95 | | } |
| | | 96 | | |
| | 3 | 97 | | return null; |
| | | 98 | | } |
| | | 99 | | |
| | 23 | 100 | | var underlyingParameterType = Nullable.GetUnderlyingType(parameter.ParameterType); |
| | | 101 | | |
| | 23 | 102 | | if (underlyingParameterType is not null && |
| | 23 | 103 | | underlyingParameterType.IsInstanceOfType(value)) |
| | | 104 | | { |
| | 2 | 105 | | return value; |
| | | 106 | | } |
| | | 107 | | |
| | 21 | 108 | | if (!parameter.ParameterType.IsInstanceOfType(value)) |
| | | 109 | | { |
| | 0 | 110 | | throw new InvalidOperationException( |
| | 0 | 111 | | $"Telegram handler '{TelegramHandlerDescriptorFormatter.GetDisplayName(selection.Handler)}' route value |
| | | 112 | | } |
| | | 113 | | |
| | 21 | 114 | | return value; |
| | | 115 | | } |
| | | 116 | | } |