2011-07-05 11 views
10

Tengo un objeto (MyObject) con una propiedad (MyProperty). Quiero obtener su nombre de tipo (es decir, String o MyClass, etc.). Yo uso:¿Cuál es el significado de "apóstrofo + número" en el tipo de objeto de propiedades con genéricos (p. Ej., "Colección`1")?

PropertyInfo propInfo = typeof(MyObject).GetProperty("MyProperty"); 
Console.WriteLine(propInfo.PropertyType.Name); 
Console.WriteLine(propInfo.PropertyType.FullName); 

No hay problema con los tipos simples, pero cuando MyProperty es un tipo genérico, que enfrento problemas en conseguir su nombre (por ejemplo Collection<String>). Imprime:

Collection`1

System.Collections.ObjectModel.Collection`1 [[System.String, mscorlib, versión = 2.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089]]

¿Qué es eso `1? ¿Y cómo puedo obtener "Collection<String>"?

+2

Collection'1 significa una colección genérica con 1 parámetro de tipo genérico –

Respuesta

11

El `` 1` significa un tipo genérico, con 1 parámetro genérico.

Una forma de conseguir la cadena es mediante el uso de la System.CodeDom, según lo sugerido por @LukeH:

using System; 
using System.CodeDom; 
using System.Collections.Generic; 
using Microsoft.CSharp; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var p = new CSharpCodeProvider()) 
      { 
       var r = new CodeTypeReference(typeof(Dictionary<string, int>)); 

       Console.WriteLine(p.GetTypeOutput(r)); 
      } 
     } 
    } 
} 

Un método alternativo es here. Ver a continuación para el código @jaredpar 's:

public static string GetFriendlyTypeName(Type type) { 
    if (type.IsGenericParameter) 
    { 
     return type.Name; 
    } 

    if (!type.IsGenericType) 
    { 
     return type.FullName; 
    } 

    var builder = new System.Text.StringBuilder(); 
    var name = type.Name; 
    var index = name.IndexOf("`"); 
    builder.AppendFormat("{0}.{1}", type.Namespace, name.Substring(0, index)); 
    builder.Append('<'); 
    var first = true; 
    foreach (var arg in type.GetGenericArguments()) 
    { 
     if (!first) 
     { 
      builder.Append(','); 
     } 
     builder.Append(GetFriendlyTypeName(arg)); 
     first = false; 
    } 
    builder.Append('>'); 
    return builder.ToString(); 
} 
+0

Es posible que desee manejar Nullables, y es posible que desee agregar un espacio después de la coma. – SLaks

+0

Si copia la fuente completa, es posible que desee acreditar a JaredPar con algo más que un enlace a la pregunta ... – Heinzi

+0

'type.GetGenericTypeDefinition(). FullName' – SLaks

8

Este es un tipo de letra interno CLR.

El número es el número de parámetros de tipo genérico, ya que los tipos pueden estar sobrecargados.
(Func`1 y Func`2 son diferentes tipos)

No hay manera integrada para obtener un nombre de tipo C# de estilo, ya que el CLR no tiene nada que ver con C#.

+5

Usted puede conseguir realmente en el C# - nombre de estilo usando CodeDom, ¡pero probablemente no me molestaría! Algo como 'using (var p = new CSharpCodeProvider()) {var r = new CodeTypeReference (propInfo.PropertyType); Console.WriteLine (p.GetTypeOutput (r)); } ' – LukeH

+0

@LukeH: Mirando la fuente, que solo maneja arreglos, no genéricos. – SLaks

+0

¡Funciona para todos los tipos genéricos que he lanzado! – LukeH

0

SLaks ya se explicó lo que `1 medios.

Sobre su segunda pregunta: Se puede obtener el nombre de los parámetros de tipo genérico mediante el uso de Type.GetGenericArguments:

if (propInfo.PropertyType.IsGenericType) { 
    Type[] typeArguments = propInfo.PropertyType.GetGenericArguments(); 
    // typeArguments now contains an array of types ({String} in your example). 
} 
+1

Quiere una cadena, no una matriz de parámetros de tipo. – SLaks

+0

@SLaks: Buen punto.Lo dejo como un ejercicio para el lector. ;-) – Heinzi

Cuestiones relacionadas