2013-05-09 88 views
14

是否有一种简单的方法,无需编写递归方法,该类型将从Type类中为泛型类型提供'用户友好'名称?在C#中为泛型类型获取用户友好的名称

E.g.对于下面的代码,我想有点像“列出<字典<诠释> >”代替简写或通过下面的代码给出全名:

var list = new List<Dictionary<int, string>>(); 
var type = list.GetType(); 

Console.WriteLine(type.Name); 
Console.WriteLine(type.FullName); 
+0

在简而言之,不。递归方法是要走的路:) – 2013-05-09 16:22:11

+0

添加了正确的HTML格式化大于和小于... – AwkwardCoder 2013-05-09 16:42:19

回答

27

根据您编辑的问题,你想是这样的:

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; 
} 
+2

我一直推荐使用'FullName'和Substring ...你也可以使用split,也可以使用'.',只是采取了最后一个''后的任何东西。' – Nevyn 2013-05-09 16:21:18

+0

这个问题明确提到“没有写递归方法”,但我看不出为什么。 – hvd 2013-05-09 16:28:50

+5

@ hvd,是的,我真的不关心OP的任意和虚假要求。 – 2013-05-09 16:34:45

0

Reflection - Getting the generic parameters from a System.Type instance

你也可以在泛型类型使用反射:

var dict = new Dictionary<string, int>(); 

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

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

所以整个代码如下:

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

       foreach (Type arg in t.GetGenericArguments()) 
       { 
        typeQueue.Enqueue(t); 
       } 
      } 
     } 
13

您可避免通过调用这已经为你提供递归方法写一个递归方法:

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<System.Collections.Generic.Dictionary<int, string>> 

这是我不清楚是否有资格作为“类似” List<Dictionary<int, string>>

3

我用这个代码,当我需要一个解决方案:

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<object> 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()); 
0

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

  • 支持所有C#关键字
  • 支持自定义翻译
  • 阵列
  • Nullables是ValueType?代替Nullable<ValueType>

这里是全码:

public static class TypeTranslator 
{ 
    private static Dictionary<Type, string> _defaultDictionary = new Dictionary<System.Type, string> 
    { 
     {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<Type, string> 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); 
    } 
}