| File: Ats\GenericMethodResolver.cs | Web Access |
| Project: src\src\Aspire.Hosting.RemoteHost\Aspire.Hosting.RemoteHost.csproj (Aspire.Hosting.RemoteHost) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Reflection; namespace Aspire.Hosting.RemoteHost.Ats; /// <summary> /// Helper for resolving generic methods from runtime arguments. /// </summary> internal static class GenericMethodResolver { /// <summary> /// Creates a closed generic method by inferring type arguments from the provided argument values. /// </summary> /// <param name="method">The open generic method.</param> /// <param name="arguments">The actual argument values.</param> /// <returns>A closed generic method with resolved type arguments.</returns> public static MethodInfo MakeGenericMethodFromArgs(MethodInfo method, object?[] arguments) { if (!method.ContainsGenericParameters) { return method; } var genericArgs = method.GetGenericArguments(); var resolvedTypes = new Type[genericArgs.Length]; var parameters = method.GetParameters(); // Infer each generic argument from the actual argument types for (var i = 0; i < genericArgs.Length; i++) { resolvedTypes[i] = InferGenericArgument(genericArgs[i], parameters, arguments) ?? typeof(object); } return method.MakeGenericMethod(resolvedTypes); } private static Type? InferGenericArgument(Type genericArg, ParameterInfo[] parameters, object?[] arguments) { for (var j = 0; j < parameters.Length && j < arguments.Length; j++) { var paramType = parameters[j].ParameterType; var argument = arguments[j]; if (argument == null) { continue; } // Direct match: parameter is the generic argument itself (e.g., T param) if (paramType == genericArg) { return argument.GetType(); } // Generic type match: extract from IResourceBuilder<T>, etc. if (paramType.IsGenericType) { var typeArgs = paramType.GetGenericArguments(); for (var k = 0; k < typeArgs.Length; k++) { if (typeArgs[k] == genericArg) { var argType = argument.GetType(); // Try direct generic type match if (argType.IsGenericType) { return argType.GetGenericArguments()[k]; } // Try to find matching interface var iface = argType.GetInterfaces() .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == paramType.GetGenericTypeDefinition()); if (iface != null) { return iface.GetGenericArguments()[k]; } } } } } return null; } }