Get the type name

后端 未结 10 842
星月不相逢
星月不相逢 2020-12-05 23:05

How i can get full right name of generic type?

For example: This code

typeof(List).Name

return

10条回答
  •  离开以前
    2020-12-05 23:34

    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.

提交回复
热议问题