在C#中获取generics类型的用户友好名称

有没有编写递归方法的简单方法,它将为Type类中的generics类型提供“用户友好”的名称?

例如,对于以下代码,我想要“List <Dictionary >”,而不是以下代码给出的简写或全名:

 var list = new List<Dictionary>(); var type = list.GetType(); Console.WriteLine(type.Name); Console.WriteLine(type.FullName); 

根据您编辑的问题,您需要以下内容:

 public static string GetFriendlyName(this Type type) { if (type == typeof(int)) return "int"; else if (type == typeof(short)) return "short"; else if (type == typeof(byte)) return "byte"; else if (type == typeof(bool)) return "bool"; else if (type == typeof(long)) return "long"; else if (type == typeof(float)) return "float"; else if (type == typeof(double)) return "double"; else if (type == typeof(decimal)) return "decimal"; else if (type == typeof(string)) return "string"; else if (type.IsGenericType) return type.Name.Split('`')[0] + "<" + string.Join(", ", type.GetGenericArguments().Select(x => GetFriendlyName(x)).ToArray()) + ">"; else return type.Name; } 

您可以通过调用已经为您提供的递归方法来避免编写递归方法:

 static string GetTypeName(Type type) { var codeDomProvider = CodeDomProvider.CreateProvider("C#"); var typeReferenceExpression = new CodeTypeReferenceExpression(new CodeTypeReference(type)); using (var writer = new StringWriter()) { codeDomProvider.GenerateCodeFromExpression(typeReferenceExpression, writer, new CodeGeneratorOptions()); return writer.GetStringBuilder().ToString(); } } 

请注意,这包括类型命名空间,但不包括程序集引用。 对于您问题中的类型,结果如下所示:

 System.Collections.Generic.List> 

我不清楚它是否符合“ List>

当我需要解决方案时,我使用了这段代码:

  public static string FriendlyName(this Type type) { if (type.IsGenericType) { var namePrefix = type.Name.Split(new [] {'`'}, StringSplitOptions.RemoveEmptyEntries)[0]; var genericParameters = type.GetGenericArguments().Select(FriendlyName).ToCsv(); return namePrefix + "<" + genericParameters + ">"; } return type.Name; } 

  public static string ToCsv(this IEnumerable collectionToConvert, string separator = ", ") { return String.Join(separator, collectionToConvert.Select(o => o.ToString())); } 

示例用法:

  var typeDisplayText = MyDataModel.GetType().FriendlyName(); 

…如果您正在创建自动生成的开发人员帮助页面,这也很有用,因为它包含通用参数名称:

 public static string DefinitionTitle(this Type type) { if (type.IsGenericType) { var namePrefix = type.Name.Split(new[] { '`' }, StringSplitOptions.RemoveEmptyEntries)[0]; var genericParameters = type.GetGenericArguments().Select(a => a.Name).ToCsv(); return namePrefix + "<" + genericParameters + ">"; } return type.Name; } 

示例用法:

  var typeDefinitionText = typeof(Dictionary<,>).DefinitionTitle()); 

reflection – 从System.Type实例获取通用参数

您还可以对generics类型使用reflection:

 var dict = new Dictionary(); Type type = dict.GetType(); Console.WriteLine("Type arguments:"); foreach (Type arg in type.GetGenericArguments()) { Console.WriteLine(" {0}", arg); } 

然后,您可以将其放入对象的扩展方法中,并在任何需要的地方使用它。 我还想补充一点,每次递归都可以写成命令式代码。

所以整个代码看起来像:

  static void GetGenericParametersNames(Type type) { Queue typeQueue = new Queue(); typeQueue.Enqueue(type); while (typeQueue.Any()) { var t = typeQueue.Dequeue(); Console.WriteLine(" {0}", arg); foreach (Type arg in t.GetGenericArguments()) { typeQueue.Enqueue(t); } } } 

建立一个更完整的柯克的答案将是这样的。 修改:

  • 支持所有C#关键字
  • 支持自定义翻译
  • 数组
  • Nullables是ValueType? 而不是Nullable

这是完整的代码:

 public static class TypeTranslator { private static Dictionary _defaultDictionary = new Dictionary { {typeof(int), "int"}, {typeof(uint), "uint"}, {typeof(long), "long"}, {typeof(ulong), "ulong"}, {typeof(short), "short"}, {typeof(ushort), "ushort"}, {typeof(byte), "byte"}, {typeof(sbyte), "sbyte"}, {typeof(bool), "bool"}, {typeof(float), "float"}, {typeof(double), "double"}, {typeof(decimal), "decimal"}, {typeof(char), "char"}, {typeof(string), "string"}, {typeof(object), "object"}, {typeof(void), "void"} }; public static string GetFriendlyName(this Type type, Dictionary translations) { if(translations.ContainsKey(type)) return translations[type]; else if (type.IsArray) return GetFriendlyName(type.GetElementType(), translations) + "[]"; else if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) return type.GetGenericArguments()[0].GetFriendlyName() + "?"; else if (type.IsGenericType) return type.Name.Split('`')[0] + "<" + string.Join(", ", type.GetGenericArguments().Select(x => GetFriendlyName(x)).ToArray()) + ">"; else return type.Name; } public static string GetFriendlyName(this Type type) { return type.GetFriendlyName(_defaultDictionary); } }