2009-10-07 11 views

risposta

11

Ok, ho fatto un sacco di ricerche e ho scoperto che typeof (Lista) ha "GetGenericArguments" che ti farà ottenere i nomi secondari. Quindi lo farei in questo modo (per 1 tipo generico, se è un multi prenderò un ciclo o qualcosa.Posso postare una funzione per questo se richiesto.

Ecco una funzione per farlo con . più argomenti generici, 'nidificate' tipi generici maniglie a cura di nuovo per rendere questo utilizzare la funzione di aggregazione:.

static string GetFullName(Type t) 
{ 
    if (!t.IsGenericType) 
     return t.Name; 
    StringBuilder sb=new StringBuilder(); 

    sb.Append(t.Name.Substring(0, t.Name.LastIndexOf("`"))); 
    sb.Append(t.GetGenericArguments().Aggregate("<", 

     delegate(string aggregate,Type type) 
      { 
       return aggregate + (aggregate == "<" ? "" : ",") + GetFullName(type); 
      } 
     )); 
    sb.Append(">"); 

    return sb.ToString(); 
} 
+0

Dovrebbe essere migliorato un po '. L'argomento generico dovrebbe essere formattato allo stesso modo, potrebbe essere di nuovo un tipo generico. Ovviamente dovrebbe supportare molti argomenti generici. –

+0

Ero in procinto di digitare una versione più complessa che gestiva quella e moltiplica, che ho appena postato. – Erich

+0

Modificato di nuovo per utilizzare gli aggregati. Controlla la cronologia delle modifiche se vuoi la versione "vecchia". La funzionalità è identica, ma volevo capire come funzionava l'aggregato, e questo era un buon modo per imparare :) – Erich

-1

Beh, questo è perché il nome del tipo in .NET realtà IS List'1. Il "'1" è la cosiddetta arità del generico e ti dice quanti parametri di tipo ci sono.

È necessario in modo che sia possibile creare più di 1 tipo generico con lo stesso "nome" ma un diverso numero di parametri di tipo generico.

Ad esempio, esistono più di un tipo "chiamato" System.Action. I veri nomi di questi sono System.Action'1, System.Action'2, System.Action'3 ecc.

Quindi, se sai che il tuo tipo è generico, puoi supporre che ci sia questo 'XX alle alla fine del nome, quindi si può solo tagliare questa parte di distanza, per esempio come questo:

string strTypeName = typeof(List<>).Name.Substring(0, typeof(List<>).Name.LastIndexOf("`")); 

PS: si prega di sostituire 'con `.

+0

Spiacente, c'è stato un errore nel mio esempio.Ho bisogno di ottenere argomenti di tipo generico (nel mio esempio: Int32) – AndreyAkinshin

+0

Questa risposta non è più pertinente (dopo che la domanda è stata modificata). – ToolmakerSteve

3

che non è troppo difficile ;-)

Va bene, ti mordo .. g Quello sotto funziona in modo recusivo e visualizza i tipi primitivi senza lo spazio dei nomi (come scritto dall'OP):

static string PrettyPrintGenericTypeName(Type typeRef) 
    { 
    var rootType = typeRef.IsGenericType 
     ? typeRef.GetGenericTypeDefinition() 
     : typeRef; 

    var cleanedName = rootType.IsPrimitive 
          ? rootType.Name 
          : rootType.ToString(); 

    if (!typeRef.IsGenericType) 
     return cleanedName; 
    else 
     return cleanedName.Substring(0, 
            cleanedName.LastIndexOf('`')) 
      + typeRef.GetGenericArguments() 
        .Aggregate("<", 
           (r, i) => 
            r 
            + (r != "<" ? ", " : null) 
            + PrettyPrintGenericTypeName(i)) 
      + ">"; 
    } 

Il cleanedName risultante è simile a questo: System.Collections.Generic.Dictionary<System.Collections.Generic.List<Int32>, ConsoleApplication2.Program+SomeType>

12

Uso delle funzioni incorporate e Linq questo può essere scritto

static string PrettyTypeName(Type t) 
{ 
    if (t.IsGenericType) 
    { 
     return string.Format(
      "{0}<{1}>", 
      t.Name.Substring(0, t.Name.LastIndexOf("`", StringComparison.InvariantCulture)), 
      string.Join(", ", t.GetGenericArguments().Select(PrettyTypeName))); 
    } 

    return t.Name; 
} 

NOTA: In una vecchia versione di C#, il compilatore richiede esplicito .ToArray():

  string.Join(", ", t.GetGenericArguments().Select(PrettyTypeName).ToArray())); 
+1

Questa dovrebbe essere la risposta accettata –

+0

In VS 2010 con .NET 3.5 (non sicuro quale versione C#), 'tGetGenericArguments(). (PrettyTypeName) 'dà errore del compilatore" * non può convertire da 'System.Collections.Generic.IEnumerable ' a 'string []' * "Fix: append' .ToArray() '. Aggiungendo per rispondere come alternativa. – ToolmakerSteve

0

Un altro esempio ho solo me stesso scritto prima di inciampare qui.

private string PrettyPrintGenericTypeName(Type p) 
    { 
     if (p.IsGenericType) { 
      var simpleName = p.Name.Substring(0, p.Name.IndexOf('`')); 
      var genericTypeParams = p.GenericTypeArguments.Select(PrettyPrintGenericTypeName).ToList(); 
      return string.Format("{0}<{1}>", simpleName, string.Join(", ", genericTypeParams)); 
     } else { 
      return p.Name; 
     } 
    } 
0

Vecchia domanda, ma oggi ne ho solo bisogno. Così ho scritto un metodo di estensione che può produrre un generico nome generico in C# in grado di gestire tipi generici nidificati a più livelli.

using System; 
using System.Text; 

public static class TypeExtensions 
{ 
    public static string GetNiceName(this Type type, bool useFullName = false) 
    { 
     if (!type.IsGenericType) { 
      return type.Name; 
     } 

     var typeNameBuilder = new StringBuilder(); 
     GetNiceGenericName(typeNameBuilder, type, useFullName); 
     return typeNameBuilder.ToString(); 
    } 

    static void GetNiceGenericName(StringBuilder sb, Type type, bool useFullName) 
    { 
     if (!type.IsGenericType) { 
      sb.Append(useFullName ? type.FullName : type.Name); 
      return; 
     } 

     var typeDef = type.GetGenericTypeDefinition(); 
     var typeName = useFullName ? typeDef.FullName : typeDef.Name; 
     sb.Append(typeName); 
     sb.Length -= typeName.Length - typeName.LastIndexOf('`'); 
     sb.Append('<'); 
     foreach (var typeArgument in type.GenericTypeArguments) { 
      GetNiceGenericName(sb, typeArgument, useFullName); 
      sb.Append(", "); 
     } 
     sb.Length -= 2; 
     sb.Append('>'); 
    } 
} 
Problemi correlati