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

C# 获取没有任何泛型信息的类型名称,c#,.net,generics,reflection,C#,.net,Generics,Reflection,如果我写: var type = typeof(List<string>); Console.WriteLine(type.Name); var type=typeof(列表); Console.WriteLine(type.Name); 它将写: 清单` 1 我希望它只写: 名单 我该怎么做? 有没有一种更聪明的方法不必使用子字符串或类似的字符串操作函数就可以做到这一点?不,没有,因为“泛型类型字符串”是类型名称的一部分。不,在名称中包含泛型算术非常有意义,因为它是使名称唯一的

如果我写:

var type = typeof(List<string>);
Console.WriteLine(type.Name);
var type=typeof(列表);
Console.WriteLine(type.Name);
它将写:

清单` 1

我希望它只写:

名单

我该怎么做?
有没有一种更聪明的方法不必使用
子字符串或类似的字符串操作函数就可以做到这一点?

不,没有,因为“泛型类型字符串”是类型名称的一部分。

不,在名称中包含泛型算术非常有意义,因为它是使名称唯一的一部分(当然还有程序集和命名空间)

这样说:和是非常不同的类型。你不希望混淆这两种类型……因此,如果你想丢失信息,你必须努力做到这一点。当然,这不是很难,可以放在助手方法中:

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(列表);
Console.WriteLine(type.GetNameWithoutGenericArity());

如果有人感兴趣,我为这个问题创建了一些扩展方法,创建了一个更“可读”的字符串

它产生类似于

List[string]
outer.inner[other.whatever]
IEnumerable[T0]
Dictionary[string:int]
试验


一个实际的用例是从泛型域对象自动转换为DTO,DTO通常不支持泛型。从C#6开始,您可以使用
nameof(List)
List[string]
outer.inner[other.whatever]
IEnumerable[T0]
Dictionary[string:int]
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;
    }
}