2013-05-09 16 views
14

Czy istnieje prosty sposób bez pisania metody rekursywnej, która zapewni "przyjazną dla użytkownika" nazwę dla ogólnego typu z klasy Type?Uzyskaj przyjazną dla użytkownika nazwę typu ogólnego w C#

E.g. Na poniższym kodzie Chcę coś jak „Lista < słownik <Int> >” zamiast skróconą lub pełną nazwę nadaną przez następujący kod:

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

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

W krótki, nie. Metoda rekursywna jest drogą do zrobienia :) –

+0

Dodano poprawne formatowanie html na większą i mniejszą niż ... – AwkwardCoder

Odpowiedz

27

oparciu o edytowanym pytanie, chcesz coś takiego:

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

Polecałem użyć 'FullName' i Substring ... Można również użyć split, na' .', właśnie bierze wszystko, co pozostało po ostatnim '.' – Nevyn

+0

W tym pytaniu pojawia się pytanie" bez pisania metody rekurencyjnej ", chociaż nie rozumiem dlaczego. – hvd

+5

@hvd, yeah, naprawdę nie dbam o arbitralne i fałszywe wymagania przez OP. –

0

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

można również użyć refleksji nad typy rodzajowe:

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

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

Następnie można umieścić go w pewnej metodzie rozszerzenia obiektu i używać go w dowolnym miejscu. Chciałbym również dodać, że każda rekursja może być napisana jako imperatywny kod.

więc cały kod będzie wyglądać następująco:

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

Można uniknąć pisania metodą rekurencyjną przez wywołanie metody rekurencyjnej, która jest już dostępne dla Ciebie:

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

pamiętać, że ta obejmuje typ przestrzenie nazw, ale wyklucza odwołania do zestawu. Dla tego typu w swoim pytaniu, wynik wygląda tak:

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

To nie jest dla mnie jasne, czy kwalifikuje się jako „coś w stylu” List<Dictionary<int, string>>.

3

Użyłem tego kodu, kiedy potrzebował rozwiązanie:

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

i

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

Przykład użycia:

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

... a jeśli tworzysz auto - generowane strony pomocy dla programistów, może to być przydatne, ponieważ zawiera ogólne nazwy parametrów:

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

przykład użycia:

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

Budowanie pełniejszą odpowiedź off Kirk będzie wyglądać następująco.Modyfikacje:

  • wsparcie dla wszystkich C# słów kluczowych
  • obsługuje materiały o niestandardowych tłumaczenia
  • Tablice
  • Nullables będąc ValueType? zamiast Nullable<ValueType>

Oto pełny kod:

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); 
    } 
} 
Powiązane problemy