How i can get full right name of generic type?
For example: This code
typeof(List).Name
return
I had problems with the other answers in some instances, i.e. with arrays, so I ended up writing yet another one. I don't use the text from Type.Name
or similar except to get the plain name of the types, because I don't know if the format is guaranteed to be the same across different .Net versions or with other implementations of the libraries (I assume it isn't).
///
/// For the given type, returns its representation in C# code.
///
/// The type.
/// Used internally, ignore.
/// Used internally, ignore.
/// The representation of the type in C# code.
public static string GetTypeCSharpRepresentation(Type type, Stack genericArgs = null, StringBuilder arrayBrackets = null)
{
StringBuilder code = new StringBuilder();
Type declaringType = type.DeclaringType;
bool arrayBracketsWasNull = arrayBrackets == null;
if (genericArgs == null)
genericArgs = new Stack(type.GetGenericArguments());
int currentTypeGenericArgsCount = genericArgs.Count;
if (declaringType != null)
currentTypeGenericArgsCount -= declaringType.GetGenericArguments().Length;
Type[] currentTypeGenericArgs = new Type[currentTypeGenericArgsCount];
for (int i = currentTypeGenericArgsCount - 1; i >= 0; i--)
currentTypeGenericArgs[i] = genericArgs.Pop();
if (declaringType != null)
code.Append(GetTypeCSharpRepresentation(declaringType, genericArgs)).Append('.');
if (type.IsArray)
{
if (arrayBrackets == null)
arrayBrackets = new StringBuilder();
arrayBrackets.Append('[');
arrayBrackets.Append(',', type.GetArrayRank() - 1);
arrayBrackets.Append(']');
Type elementType = type.GetElementType();
code.Insert(0, GetTypeCSharpRepresentation(elementType, arrayBrackets : arrayBrackets));
}
else
{
code.Append(new string(type.Name.TakeWhile(c => char.IsLetterOrDigit(c) || c == '_').ToArray()));
if (currentTypeGenericArgsCount > 0)
{
code.Append('<');
for (int i = 0; i < currentTypeGenericArgsCount; i++)
{
code.Append(GetTypeCSharpRepresentation(currentTypeGenericArgs[i]));
if (i < currentTypeGenericArgsCount - 1)
code.Append(',');
}
code.Append('>');
}
if (declaringType == null && !string.IsNullOrEmpty(type.Namespace))
{
code.Insert(0, '.').Insert(0, type.Namespace);
}
}
if (arrayBracketsWasNull && arrayBrackets != null)
code.Append(arrayBrackets.ToString());
return code.ToString();
}
I have tested it with crazy types like this, and so far it has worked perfectly:
class C
{
public class D
{
public class E
{
public class K
{
public class P
{
public struct Q
{
}
}
}
}
}
}
type = typeof(List.E.K[,][], Action[], double[][,]>, float>.P.Q>>[][,][,,,][][,,]);
// Returns "System.Collections.Generic.List.E.K[,][],System.Action[],System.Double[][,]>,System.Single>.P.Q>>[][,][,,,][][,,]":
GetTypeCSharpRepresentation(type);
There may still be some gotchas I didn't think about, but there's a known one: to retrieve the names, I only get characters that meet the condition char.IsLetterOrDigit(c) || c == '_'
until one that doesn't is found, so any names of types that use allowed characters that don't meet the condition will fail.