generics类型的C#声明

是否有可能得到一个reflection获得的类型的“c#名称”,如:

System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 

我想得到:

 List 

没有拆分字符串有可能吗? 例如,使用Reflection。

谢谢!

是的,你可以通过使用CodeDomCSharpCodeProvider来分割,解析或操​​作字符串来CSharpCodeProvider

 using CodeDom; using Microsoft.CSharp; // ... Type yourType = typeof(List); // for example using (var provider = new CSharpCodeProvider()) { var typeRef = new CodeTypeReference(yourType); Console.WriteLine(provider.GetTypeOutput(typeRef)); } 

(您可能需要执行一些额外的字符串操作来删除名称空间前缀。例如,如果您希望输出为List而不是System.Collections.Generic.List 。)

不是直接的,但你可以检查类型本身来弄清楚。

 public static string TypeName(Type t) { if (!t.IsGenericType) return t.Name; StringBuilder ret = new StringBuilder(); ret.Append(t.Name).Append("<"); bool first = true; foreach(var arg in t.GetGenericArguments()) { if (!first) ret.Append(", "); first = false; ret.Append(TypeName(arg)); } ret.Append(">"); return ret.ToString(); } 

你需要解析一个字符串,如:

 t`x[[a(,b,c,d)]] 

其中t是实际类型; x – 通用参数的数量; a,b,c,d等 – 通用的aguments

…没有分裂弦?

AFAIK, 没有

您可以检查类型以确定它是否嵌套,以及它是通用构造还是基本类型。 特别是我意识到嵌套generics类型在类型名称字符串的末尾列出了它的generics参数。 在文档Type.GetType Method(String)中提到了这一点。

我已经部分解决了这个任务,我的解决方案通过了以下测试。

  [TestMethod] public void Tests() { Assert.AreEqual("int",typeof(int).ToCSharpMethodReturnTypeName()); Assert.AreEqual("int[]",typeof(int[]).ToCSharpMethodReturnTypeName()); Assert.AreEqual("int?", typeof(int?).ToCSharpMethodReturnTypeName()); Assert.AreEqual("UnitTypeFriendlyNamesExtensionsTest.Inner2>.SubInner,object>", typeof(Inner2>.SubInner,object>).ToCSharpMethodReturnTypeName()); Assert.ThrowsException(()=> typeof(Inner2>.SubInner, object>).DeclaringType.ToCSharpMethodReturnTypeName()); var t = typeof(TestGenericReturnType); var m = t.GetMethod("GetService"); var tt = m.ReturnType; Assert.AreEqual("DateTime",tt.ToCSharpMethodReturnTypeName()); Assert.AreEqual("IDictionary",typeof(IDictionary).ToCSharpMethodReturnTypeName()); Assert.AreEqual("IList",typeof(IList).ToCSharpMethodReturnTypeName()); Assert.AreEqual("UnitTypeFriendlyNamesExtensionsTest.Astruc?",typeof(Astruc?).ToCSharpMethodReturnTypeName()); Assert.AreEqual("UnitTypeFriendlyNamesExtensionsTest.Inner", typeof(Inner).ToCSharpMethodReturnTypeName()); } 

extensions类处理嵌套和generics构造类型以及基本类型。

 public static class TypeFriendlyNamesExtensions { private static readonly Dictionary TypeToFriendlyName = new Dictionary { {typeof(string), "string"}, {typeof(object), "object"}, {typeof(bool), "bool"}, {typeof(byte), "byte"}, {typeof(char), "char"}, {typeof(decimal), "decimal"}, {typeof(double), "double"}, {typeof(short), "short"}, {typeof(int), "int"}, {typeof(long), "long"}, {typeof(sbyte), "sbyte"}, {typeof(float), "float"}, {typeof(ushort), "ushort"}, {typeof(uint), "uint"}, {typeof(ulong), "ulong"}, {typeof(void), "void"} }; public static string ToCSharpMethodReturnTypeName(this Type type) { var sb = new StringWriter(); ToCSharpNameEntry2(sb, type); return sb.ToString(); } private static void ToCSharpNameEntry2(TextWriter sb, Type type0) { var list = GetContainingTypeList(type0); var usedGenericArgumentCounter = 0; HandleNestedLevel(sb, list, 0, ref usedGenericArgumentCounter); foreach (var ix in Enumerable.Range(1, list.Count - 1)) { sb.Write("."); HandleNestedLevel(sb, list, ix, ref usedGenericArgumentCounter); } } private static void HandleNestedLevel(TextWriter sb, IReadOnlyList list, int ix, ref int usedGenericArgumentCounter) { var type = list[ix]; if (TypeToFriendlyName.TryGetValue(type, out string fname)) { sb.Write(fname); return; } if (type.IsGenericParameter) { sb.Write(type.Name); return; } if (type.IsArray) { ToCSharpNameEntry2(sb, type.GetElementType()); sb.Write("[]"); return; } if (type.IsGenericType) { var innermostType = list[list.Count - 1]; var args = list[list.Count - 1].GenericTypeArguments; if (!type.IsConstructedGenericType) { if (innermostType.IsConstructedGenericType) { var sname = GetSname(type); sb.Write(sname); sb.Write("<"); ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]); var loopCounter = ((TypeInfo) type).GenericTypeParameters.Length; while (0 < --loopCounter) { sb.Write(","); ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]); } sb.Write(">"); return; } throw new NotImplementedException(); } if (typeof(Nullable<>) == type.GetGenericTypeDefinition()) { ToCSharpNameEntry2(sb, args[0]); sb.Write("?"); return; } var cname = GetSname(type); sb.Write(cname); sb.Write("<"); ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]); while (usedGenericArgumentCounter < args.Length) { sb.Write(","); ToCSharpNameEntry2(sb, args[usedGenericArgumentCounter++]); } sb.Write(">"); return; } if (type.IsPointer) { ToCSharpNameEntry2(sb, type); sb.Write("*"); return; } sb.Write(type.Name); } private static string GetSname(Type type) { var name = type.Name; return name.Substring(0, name.IndexOf('`')); } private static List GetContainingTypeList(Type type) { var list = new List {type}; var t = type; while (t.IsNested) { t = t.DeclaringType; list.Insert(0, t); } return list; } private static void ToCSharpNameEntry(StringBuilder sb, Type type) { var genericTypeArguments = type.GenericTypeArguments; var usedGenericTypeCounter = 0; ToCSharpNameRecursive(sb, type, genericTypeArguments, ref usedGenericTypeCounter); } private static void ToCSharpNameRecursive(StringBuilder sb, Type type, IReadOnlyList genericTypeArguments, ref int genericTypesCounter) { if (TypeToFriendlyName.TryGetValue(type, out string res)) { sb.Append(res); return; } HandleNonPriminiveTypes(sb, type, genericTypeArguments, ref genericTypesCounter); } private static void HandleNonPriminiveTypes(StringBuilder sb, Type type, IReadOnlyList typeGenericTypeArguments, ref int genericTypesCounter) { var list = new List(); var t = type; list.Add(t); while (t.IsNested) { t = t.DeclaringType; list.Add(t); } list.Reverse(); foreach (var type1 in list) { HandleNestedLevel(sb, type1, typeGenericTypeArguments, ref genericTypesCounter); sb.Append("."); } sb.Length -= 1; } private static void HandleNestedLevel(StringBuilder sb, Type type, IReadOnlyList typeGenericTypeArguments, ref int genericTypesCounter) { var name = type.Name; if (type.IsGenericType) { var info = type.GetTypeInfo(); var def = info.GetGenericTypeDefinition(); var psLength = info.IsConstructedGenericType ? info.GenericTypeArguments.Length : info.GenericTypeParameters.Length; if (typeof(Nullable<>) == def) { var type1 = typeGenericTypeArguments[genericTypesCounter++]; ToCSharpNameEntry(sb, type1); sb.Append("?"); return; } var n = name.Substring(0, name.IndexOf("`", StringComparison.InvariantCultureIgnoreCase)); sb.Append(n); sb.Append("<"); for (var i = 0; i < psLength; i++) { ToCSharpNameEntry(sb, typeGenericTypeArguments[genericTypesCounter++]); sb.Append(","); } sb.Length -= 1; sb.Append(">"); return; } if (type.IsArray) { var type1 = type.GetElementType(); ToCSharpNameEntry(sb, type1); sb.Append("[]"); return; } sb.Append(name); } } 

我在编写要由Roslyn编译的源文本时使用扩展方法