using System.Reflection; using System.Runtime.CompilerServices; namespace AyCode.Services.Server.SignalRs; public static class ExtensionMethods { /// /// Invokes a method and properly unwraps Task/Task<T> results. /// Handles both async methods and methods returning Task directly (e.g., Task.FromResult). /// public static object? InvokeMethod(this MethodInfo methodInfo, object obj, params object[]? parameters) { var result = methodInfo.Invoke(obj, parameters); if (result == null) return null; // Check if result is a Task (this handles both async methods AND Task.FromResult) if (result is Task task) { // Wait for task completion task.GetAwaiter().GetResult(); // Check if it's Task to extract the actual result var taskType = task.GetType(); if (taskType.IsGenericType) { // Get the Result property from Task var resultProperty = taskType.GetProperty("Result"); if (resultProperty != null) { return resultProperty.GetValue(task); } } // Non-generic Task - no result return null; } // Handle ValueTask var type = result.GetType(); if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTask<>)) { // Convert ValueTask to Task and get result var asTaskMethod = type.GetMethod("AsTask"); if (asTaskMethod != null) { var taskResult = (Task)asTaskMethod.Invoke(result, null)!; taskResult.GetAwaiter().GetResult(); var resultProperty = taskResult.GetType().GetProperty("Result"); return resultProperty?.GetValue(taskResult); } } // Handle non-generic ValueTask if (result is ValueTask valueTask) { valueTask.AsTask().GetAwaiter().GetResult(); return null; } // Not a Task - return directly return result; } }