AyCode.Core/AyCode.Services.Server/SignalRs/ExtensionMethods.cs

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&lt;T&gt; 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;
}
}