<PackageReference Include="NUnit" Version="3.8.0" />

GenericMethodHelper

public class GenericMethodHelper
GenericMethodHelper is able to deduce the Type arguments for a generic method from the actual arguments provided.
using NUnit.Compatibility; using System; using System.Reflection; namespace NUnit.Framework.Internal { public class GenericMethodHelper { private MethodInfo Method { get; set; } private Type[] TypeParms { get; set; } private Type[] TypeArgs { get; set; } private Type[] ParmTypes { get; set; } public GenericMethodHelper(MethodInfo method) { Guard.ArgumentValid(method.IsGenericMethod, "Specified method must be generic", "method"); Method = method; TypeParms = Method.GetGenericArguments(); TypeArgs = new Type[TypeParms.Length]; ParameterInfo[] parameters = Method.GetParameters(); ParmTypes = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { ParmTypes[i] = parameters[i].ParameterType; } } public Type[] GetTypeArguments(object[] argList) { Guard.ArgumentValid(argList.Length == ParmTypes.Length, "Supplied arguments do not match required method parameters", "argList"); for (int i = 0; i < ParmTypes.Length; i++) { object obj = argList[i]; if (obj != null) { Type type = obj.GetType(); TryApplyArgType(ParmTypes[i], type); } } return TypeArgs; } private void TryApplyArgType(Type parmType, Type argType) { if (parmType.IsGenericParameter) ApplyArgType(parmType, argType); else if (parmType.GetTypeInfo().get_ContainsGenericParameters()) { Type[] genericArguments = TypeExtensions.GetGenericArguments(parmType); if (argType.HasElementType) ApplyArgType(genericArguments[0], argType.GetElementType()); else if (argType.GetTypeInfo().get_IsGenericType() && IsAssignableToGenericType(argType, parmType)) { Type[] genericArguments2 = TypeExtensions.GetGenericArguments(argType); if (genericArguments2.Length == genericArguments.Length) { for (int i = 0; i < genericArguments.Length; i++) { TryApplyArgType(genericArguments[i], genericArguments2[i]); } } } } } private void ApplyArgType(Type parmType, Type argType) { int genericParameterPosition = parmType.GenericParameterPosition; TypeArgs[genericParameterPosition] = TypeHelper.BestCommonType(TypeArgs[genericParameterPosition], argType); } private bool IsAssignableToGenericType(Type givenType, Type genericType) { Type[] interfaces = TypeExtensions.GetInterfaces(givenType); foreach (Type type in interfaces) { if (type.GetTypeInfo().get_IsGenericType()) { Type genericTypeDefinition = type.GetGenericTypeDefinition(); if (genericTypeDefinition.get_Name() == genericType.get_Name() && genericTypeDefinition.Namespace == genericType.Namespace) return true; } } if (givenType.GetTypeInfo().get_IsGenericType()) { Type genericTypeDefinition2 = givenType.GetGenericTypeDefinition(); if (genericTypeDefinition2.get_Name() == genericType.get_Name() && genericTypeDefinition2.Namespace == genericType.Namespace) return true; } Type baseType = givenType.GetTypeInfo().get_BaseType(); if ((object)baseType == null) return false; return IsAssignableToGenericType(baseType, genericType); } } }