使用C#上的Reflection获取格式良好的GenericType-Name

我需要在代码中以声明的forms获得generics类型的名称。

例如:对于List ,我想获取字符串“List ”。 在这种情况下,Standart属性Type.Name返回“List`1”。

编辑:示例已修复

好的,我做了很多研究,发现typeof(List)有“GetGenericArguments”,可以获得子名称。 所以我会这样做(对于1个generics类型,如果是多个,它会采取循环或其他东西。如果请求,我可以发布一个函数。

这是一个使用多个generics参数,处理’嵌套’generics类型的函数。 再次编辑以使用Aggregate函数:

static string GetFullName(Type t) { if (!t.IsGenericType) return t.Name; StringBuilder sb=new StringBuilder(); sb.Append(t.Name.Substring(0, t.Name.LastIndexOf("`"))); sb.Append(t.GetGenericArguments().Aggregate("<", delegate(string aggregate,Type type) { return aggregate + (aggregate == "<" ? "" : ",") + GetFullName(type); } )); sb.Append(">"); return sb.ToString(); } 

使用内置函数和Linq可以编写

 static string PrettyTypeName(Type t) { if (t.IsGenericType) { return string.Format( "{0}<{1}>", t.Name.Substring(0, t.Name.LastIndexOf("`", StringComparison.InvariantCulture)), string.Join(", ", t.GetGenericArguments().Select(PrettyTypeName))); } return t.Name; } 

注意:在较旧版本的C#中,编译器需要显式.ToArray()

  string.Join(", ", t.GetGenericArguments().Select(PrettyTypeName).ToArray())); 

这不是太难。 😉

好吧,我会咬人…… g下面的那个可以反复使用并显示没有命名空间的原始类型(就像OP写的那样):

  static string PrettyPrintGenericTypeName(Type typeRef) { var rootType = typeRef.IsGenericType ? typeRef.GetGenericTypeDefinition() : typeRef; var cleanedName = rootType.IsPrimitive ? rootType.Name : rootType.ToString(); if (!typeRef.IsGenericType) return cleanedName; else return cleanedName.Substring(0, cleanedName.LastIndexOf('`')) + typeRef.GetGenericArguments() .Aggregate("<", (r, i) => r + (r != "<" ? ", " : null) + PrettyPrintGenericTypeName(i)) + ">"; } 

生成的cleaningName如下所示: System.Collections.Generic.Dictionary, ConsoleApplication2.Program+SomeType>

我刚刚在这里磕磕绊绊的另一个例子。

  private string PrettyPrintGenericTypeName(Type p) { if (p.IsGenericType) { var simpleName = p.Name.Substring(0, p.Name.IndexOf('`')); var genericTypeParams = p.GenericTypeArguments.Select(PrettyPrintGenericTypeName).ToList(); return string.Format("{0}<{1}>", simpleName, string.Join(", ", genericTypeParams)); } else { return p.Name; } } 

老问题,但我今天只需要这个。 所以我编写了一个扩展方法,可以输出漂亮的C#格式化通用名称,可以处理多级嵌套generics类型。

 using System; using System.Text; public static class TypeExtensions { public static string GetNiceName(this Type type, bool useFullName = false) { if (!type.IsGenericType) { return type.Name; } var typeNameBuilder = new StringBuilder(); GetNiceGenericName(typeNameBuilder, type, useFullName); return typeNameBuilder.ToString(); } static void GetNiceGenericName(StringBuilder sb, Type type, bool useFullName) { if (!type.IsGenericType) { sb.Append(useFullName ? type.FullName : type.Name); return; } var typeDef = type.GetGenericTypeDefinition(); var typeName = useFullName ? typeDef.FullName : typeDef.Name; sb.Append(typeName); sb.Length -= typeName.Length - typeName.LastIndexOf('`'); sb.Append('<'); foreach (var typeArgument in type.GenericTypeArguments) { GetNiceGenericName(sb, typeArgument, useFullName); sb.Append(", "); } sb.Length -= 2; sb.Append('>'); } } 

嗯,那是因为.NET中的类型名称实际上是IS List’1。 “’1”是generics的所谓arity,它告诉你有多少类型参数。

这是必需的,这样您就可以使用相同的“名称”创建超过1个generics类型,但使用不同数量的generics类型参数。

例如,有超过1种类型“被称为”System.Action。 这些的真实名称是System.Action’1,System.Action’2,System.Action’3等。

所以,如果你知道你的类型是通用的,你可以假设在名称的末尾有这个’XX,所以你可以把这部分切掉,比如这样:

 string strTypeName = typeof(List<>).Name.Substring(0, typeof(List<>).Name.LastIndexOf("`")); 

PS:请用’替换’。