67 lines
2.2 KiB
C#
67 lines
2.2 KiB
C#
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace AyCode.Services.Server.SignalRs;
|
|
|
|
public static class ExtensionMethods
|
|
{
|
|
/// <summary>
|
|
/// Invokes a method and properly unwraps Task/Task<T> results.
|
|
/// Handles both async methods and methods returning Task directly (e.g., Task.FromResult).
|
|
/// </summary>
|
|
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<T> to extract the actual result
|
|
var taskType = task.GetType();
|
|
if (taskType.IsGenericType)
|
|
{
|
|
// Get the Result property from Task<T>
|
|
var resultProperty = taskType.GetProperty("Result");
|
|
if (resultProperty != null)
|
|
{
|
|
return resultProperty.GetValue(task);
|
|
}
|
|
}
|
|
|
|
// Non-generic Task - no result
|
|
return null;
|
|
}
|
|
|
|
// Handle ValueTask<T>
|
|
var type = result.GetType();
|
|
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTask<>))
|
|
{
|
|
// Convert ValueTask<T> to Task<T> 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;
|
|
}
|
|
} |