<PackageReference Include="NUnit" Version="3.0.0-rc-3" />

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.IO; using System.Reflection; using System.Text; using System.IO; using System.Text; 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 (IntrospectionExtensions.GetTypeInfo(parmType).ContainsGenericParameters) { Type[] genericArguments = parmType.GetGenericArguments(); if (argType.HasElementType) ApplyArgType(genericArguments[0], argType.GetElementType()); else if (IntrospectionExtensions.GetTypeInfo(argType).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(); Type[] array = interfaces; foreach (Type type in array) { if (IntrospectionExtensions.GetTypeInfo(type).IsGenericType) { Type genericTypeDefinition = type.GetGenericTypeDefinition(); if (genericTypeDefinition.Name == genericType.Name && genericTypeDefinition.Namespace == genericType.Namespace) return true; } } if (IntrospectionExtensions.GetTypeInfo(givenType).IsGenericType) { Type genericTypeDefinition2 = givenType.GetGenericTypeDefinition(); if (genericTypeDefinition2.Name == genericType.Name && genericTypeDefinition2.Namespace == genericType.Namespace) return true; } Type baseType = IntrospectionExtensions.GetTypeInfo(givenType).BaseType; if (baseType == (Type)null) return false; return IsAssignableToGenericType(baseType, genericType); } } } namespace NUnit.Framework.Internal { public class InternalTraceWriter : TextWriter { private TextWriter writer; private object myLock = new object(); public override Encoding Encoding => writer.Encoding; public InternalTraceWriter(string logPath) { writer = new StreamWriter(new FileStream(logPath, FileMode.Append, FileAccess.Write, FileShare.Write)) { AutoFlush = true }; } public InternalTraceWriter(TextWriter writer) { this.writer = writer; } public override void Write(char value) { lock (myLock) { writer.Write(value); } } public override void Write(string value) { lock (myLock) { base.Write(value); } } public override void WriteLine(string value) { writer.WriteLine(value); } protected override void Dispose(bool disposing) { if (disposing && writer != null) { writer.Flush(); writer.Dispose(); writer = null; } base.Dispose(disposing); } public override void Flush() { if (writer != null) writer.Flush(); } } }