/// <summary> /// If the type if UnknownType, it will search all the dependencies for the specified type. /// If the type is not unknown type it will just return the type directly. /// This gets around the problem that types are only known for the assembly they are included in. /// </summary> /// <param name="type">The type to check.</param> /// <param name="compilation">The compilation which contains all the assemblies and dependencies.</param> /// <returns>The concrete type if one can be found.</returns> public static IType GetRealType(this IType type, ICompilation compilation) { // If the type is UnknownType, check other assemblies we have as dependencies first, // since UnknownType is only if it's unknown in the current assembly only. // This scenario is fairly common with types in the netstandard libraries, eg System.EventHandler. var newType = type; if (newType is UnknownType || newType.Kind == TypeKind.Unknown) { if (newType.TypeParameterCount == 0) { newType = compilation.GetReferenceTypeDefinitionsWithFullName(newType.ReflectionName).FirstOrDefault(); } else if (newType is ParameterizedType paramType) { var genericType = compilation.GetReferenceTypeDefinitionsWithFullName(paramType.GenericType.ReflectionName).FirstOrDefault(); var typeArguments = newType.TypeArguments.Select(x => GetRealType(x, compilation)); newType = new ParameterizedType(genericType, typeArguments); } } return(newType ?? type); }