获取没有任何泛型信息的类型名称

时间:2011-06-17 13:09:59

标签: c# .net generics reflection

如果我写:

var type = typeof(List<string>);
Console.WriteLine(type.Name);

它会写:

  

List`1

我希望它只写:

  

列表

我该怎么做? 有没有更聪明的方法来实现它而不必使用Substring或类似的字符串操作函数?

4 个答案:

答案 0 :(得分:30)

不,它在名称中包含泛型arity是完全合理的 - 因为它是使名称唯一的部分(当然还有程序集和命名空间)。

这样说:System.NullableSystem.Nullable<T>是非常不同的类型。你不希望混淆这两个......所以,如果你希望丢失信息,那么你将不得不努力去做。当然,这并不是很难,可以用辅助方法:

public static string GetNameWithoutGenericArity(this Type t)
{
    string name = t.Name;
    int index = name.IndexOf('`');
    return index == -1 ? name : name.Substring(0, index);
}

然后:

var type = typeof(List<string>);
Console.WriteLine(type.GetNameWithoutGenericArity());

答案 1 :(得分:2)

不,它没有,因为“generic-type-string”是类型名称的一部分。

答案 2 :(得分:2)

如果有人感兴趣,我为这个问题创建了一些扩展方法,创建了更多可读的&#34;串

它产生类似

的东西
List[string]
outer.inner[other.whatever]
IEnumerable[T0]
Dictionary[string:int]

测试here

public static class TypeEx
{
    public static string GetTypeName(this Type type)
    {
        if (type == null)
            throw new ArgumentNullException(nameof(type));

        if (!type.IsGenericType)
            return type.GetNestedTypeName();

        StringBuilder stringBuilder = new StringBuilder();
        _buildClassNameRecursiv(type, stringBuilder);
        return stringBuilder.ToString();
    }

    private static void _buildClassNameRecursiv(Type type, StringBuilder classNameBuilder, int genericParameterIndex = 0)
    {
        if (type.IsGenericParameter)
            classNameBuilder.AppendFormat("T{0}", genericParameterIndex + 1);
        else if (type.IsGenericType)
        {
            classNameBuilder.Append(GetNestedTypeName(type) + "[");
            int subIndex = 0;
            foreach (Type genericTypeArgument in type.GetGenericArguments())
            {
                if (subIndex > 0)
                    classNameBuilder.Append(":");

                _buildClassNameRecursiv(genericTypeArgument, classNameBuilder, subIndex++);
            }
            classNameBuilder.Append("]");
        }
        else
            classNameBuilder.Append(type.GetNestedTypeName());
    }

    public static string GetNestedTypeName(this Type type)
    {
        if (type == null)
            throw new ArgumentNullException(nameof(type));
        if (!type.IsNested)
            return type.Name;

        StringBuilder nestedName = new StringBuilder();
        while(type != null)
        {
            if(nestedName.Length>0)
                nestedName.Insert(0,'.');

            nestedName.Insert(0, _getTypeName(type));

            type = type.DeclaringType;
        }
        return nestedName.ToString();
    }

    private static string _getTypeName(Type type)
    {
        return type.IsGenericType ? type.Name.Split('`')[0]: type.Name;
    }
}

答案 3 :(得分:0)

 Console.WriteLine(type.GetGenericTypeDefinition().UnderlyingSystemType.Name)