2013-05-09 16 views
14

Gibt es einen einfachen Weg, ohne eine rekursive Methode zu schreiben, die einen 'benutzerfreundlichen' Namen für einen generischen Typ aus der Klasse Type gibt?Benutzerfreundlicher Name für generischen Typ in C#

z. Für den folgenden Code ich etwas will, wie ‚List < Wörterbuch <Int> >‘ anstelle der Stenografie oder vollständigen Namen durch den folgenden Code angegeben:

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

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

In kurz, nein. Rekursive Methode ist der Weg zu gehen :) –

+0

Hinzugefügt die richtige HTML-Formatierung für größere und weniger als ... – AwkwardCoder

Antwort

27

Basierend auf Ihrer editierten Frage, wollen Sie etwas wie folgt aus:

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

Ich würde gehen mit 'FullName' und Substring ... Sie könnten auch Split verwenden, auf der' .', das gerade Nehmen, was auch immer nach dem letzten '.' – Nevyn

+0

übrig bleibt Die Frage erwähnt spezifisch" ohne eine rekursive Methode zu schreiben ", obwohl ich nicht sehen kann, warum. – hvd

+5

@hvd, ja, ich interessiere mich nicht wirklich für willkürliche und falsche Anforderungen von einem OP. –

0

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

Sie auch Reflexion über generische Typen verwenden:

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

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

Sie können es dann in eine Erweiterungsmethode für ein Objekt einfügen und es überall verwenden, wo Sie es brauchen. Ich möchte auch hinzufügen, dass jede Rekursion als Imperativ-Code geschrieben werden kann.

So ist der ganze Code wird wie folgt aussehen:

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

Sie vermeiden können, eine rekursive Methode zu schreiben, indem die rekursive Methode aufrufen, die bereits für Sie zur Verfügung gestellt hat:

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(); 
    } 
} 

Beachten Sie, dass dies die Art umfasst Namespaces, schließt jedoch die Assembly-Referenzen aus. Für den Typ in Frage, sieht das Ergebnis wie folgt aus:

System.Collections.Generic.List<System.Collections.Generic.Dictionary<int, string>> 

Es ist mir nicht klar, ob das qualifiziert als „so etwas wie“ List<Dictionary<int, string>>.

3

ich diesen Code verwendet, wenn ich eine Lösung benötigt:

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

und

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

Beispiel Nutzung:

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

... und wenn Sie Auto sind die Schaffung -entwickelten Entwickler-Hilfeseiten kann dies auch nützlich sein, da es die generischen Parameternamen enthält:

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

Beispiel Nutzung:

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

eine vollständigere Antwort weg von Kirks Gebäude würde wie folgt aussehen.Änderungen:

  • Unterstützung für alle C# keywords
  • Unterstützt benutzerdefinierte-Übersetzungen
  • Arrays
  • nullables sein ValueType? statt Nullable<ValueType>

Hier vollständige Code:

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); 
    } 
}