2013-05-09 76 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); 
    } 
}