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;
}
}