2009-10-07 17 views

Respuesta

11

Ok, he investigado un montón y descubrí que typeof (List) tiene "GetGenericArguments", que le proporcionará los nombres secundarios. Así que lo haría de esta manera (para 1 tipo genérico, si es multi, tomará un bucle o algo. Puedo publicar una función para eso si es necesario.

Aquí hay una función para hacerlo . múltiples argumentos genéricos, 'anidados' tipos genéricos manijas editar de nuevo para que este utilice la función de agregado:.

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

Debería mejorarse un poco. El argumento genérico debe formatearse de la misma manera, podría ser un tipo genérico de nuevo. Por supuesto, debe admitir muchos argumentos genéricos. –

+0

Estaba en el proceso de tipear una versión más compleja que manejaba eso y múltiplos, que acabo de publicar. – Erich

+0

Editado nuevamente para usar agregados. Verifique el historial de edición si quiere la versión 'anterior'. La funcionalidad es idéntica, pero quería averiguar cómo funcionaba el agregado, y esta era una buena forma de aprender :) – Erich

-1

Bueno, eso es porque el nombre del tipo en .NET realidad ES List'1. El '' 1 '' es la llamada aridad del genérico, y te dice cuántos parámetros de tipo hay.

Es necesario para que pueda crear más de 1 tipo genérico con el mismo "nombre" pero una cantidad diferente de parámetros de tipo genérico.

Por ejemplo, hay más de 1 tipo "llamado" System.Action. Los nombres reales de estos son System.Action'1, System.Action'2, System.Action'3, etc.

Por lo tanto, si sabe que su tipo es genérico, puede suponer que existe este 'XX en al final del nombre, por lo que sólo podría cortar esta parte de distancia, por ejemplo, así:

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

PD: por favor, reemplace 'con'.

+0

Disculpa, hay un error en mi ejemplo.Necesito un argumento de tipo genérico (en mi ejemplo: Int32) – AndreyAkinshin

+0

Esta respuesta ya no es relevante (después de que la pregunta fue editada). – ToolmakerSteve

3

Eso no es demasiado duro ;-)

está bien, voy a morder .. g El siguiente funciona de forma recusiva y muestra los tipos primitivos sin el espacio de nombres (como el OP escribió):

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

El cleanedName resultante es la siguiente: System.Collections.Generic.Dictionary<System.Collections.Generic.List<Int32>, ConsoleApplication2.Program+SomeType>

12

Uso de las funciones y LINQ incorporadas Esto se puede escribir

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: En una versión anterior de C#, compilador requiere explícita .ToArray():

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

Esta debería ser la respuesta aceptada. –

+0

En VS 2010 con .NET 3.5 (no estoy seguro de qué versión de C#), 't.GetGenericArguments(). Seleccione (PrettyTypeName) 'da error de compilador" * no se puede convertir de 'System.Collections.Generic.IEnumerable ' a 'string []' * "Fix: append' .ToArray() '. Agregar a la respuesta como una alternativa. – ToolmakerSteve

0

Otro ejemplo que acabo de escribir antes de tropezar aquí.

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

Pregunta anterior, pero solo tengo la necesidad de esto hoy. Así que escribí un método de extensión que puede dar como resultado un nombre genérico con formato C# agradable que puede manejar tipos genéricos anidados multinivel.

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