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();
}
}
}