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

GenericMethodHelper

public class GenericMethodHelper
GenericMethodHelper is able to deduce the Type arguments for a generic method from the actual arguments provided.
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().ContainsGenericParameters) { Type[] genericArguments = parmType.GetGenericArguments(); if (argType.HasElementType) ApplyArgType(genericArguments[0], argType.GetElementType()); else if (argType.GetTypeInfo().IsGenericType && IsAssignableToGenericType(argType, parmType)) { Type[] genericArguments2 = argType.GetGenericArguments(); 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 = givenType.GetInterfaces(); foreach (Type type in interfaces) { if (type.GetTypeInfo().IsGenericType) { Type genericTypeDefinition = type.GetGenericTypeDefinition(); if (genericTypeDefinition.Name == genericType.Name && genericTypeDefinition.Namespace == genericType.Namespace) return true; } } if (givenType.GetTypeInfo().IsGenericType) { Type genericTypeDefinition2 = givenType.GetGenericTypeDefinition(); if (genericTypeDefinition2.Name == genericType.Name && genericTypeDefinition2.Namespace == genericType.Namespace) return true; } Type baseType = givenType.GetTypeInfo().BaseType; if (baseType == (Type)null) return false; return IsAssignableToGenericType(baseType, genericType); } } }