/// <summary> /// Substitute references to type parameters from 'typeDef' /// with type arguments from 'typeArgs' in type 'type'. /// </summary> internal static Type Substitute(this Type type, Type typeDef, Type[] typeArgs) { Debug.Assert(typeDef.IsGenericTypeDefinition); Debug.Assert(typeDef.GetGenericArguments().Length == typeArgs.Length); if (type.IsGenericType) { var builder = ArrayBuilder <Type> .GetInstance(); foreach (var t in type.GetGenericArguments()) { builder.Add(t.Substitute(typeDef, typeArgs)); } var typeDefinition = type.GetGenericTypeDefinition(); return(typeDefinition.MakeGenericType(builder.ToArrayAndFree())); } else if (type.IsArray) { var elementType = type.GetElementType(); elementType = elementType.Substitute(typeDef, typeArgs); var n = type.GetArrayRank(); return((n == 1) ? elementType.MakeArrayType() : elementType.MakeArrayType(n)); } else if (type.IsPointer) { var elementType = type.GetElementType(); elementType = elementType.Substitute(typeDef, typeArgs); return(elementType.MakePointerType()); } else if (type.IsGenericParameter) { if (type.DeclaringType.Equals(typeDef)) { var ordinal = type.GenericParameterPosition; return(typeArgs[ordinal]); } } return(type); }