2011-01-04 6 views
34

básicamente estoy construyendo una plantilla T4 muy genérica y una de las cosas que necesito hacer es decir imprimir variable.ToString(). Sin embargo, quiero que evalúe las listas y las haga avanzar y, en su lugar, imprima ListItem.ToString(). Mi plantilla T4 no sabe qué tipo de variable será antes de tiempo, por eso es tan genérico.Cómo comprobar si una variable es un IEnumerable de algún tipo

Pero mi código actual que se genera el siguiente aspecto:

if(variable!=null) 
    if(variable is IEnumerable) //error here 
    foreach(var item in variable) 
     Write(item.ToString()); 

me sale un error de compilación en la línea marcada por "Uso del tipo genérico System.Generic.Collections.IEnumerable requiere argumento de un tipo"

Sin embargo, en realidad no me importa de qué tipo es, solo quiero saber si puedes enfocar la variable. ¿Qué código debería usar en su lugar?

Respuesta

48

Ya ha aceptado una respuesta, sin embargo, dado que el genérico IEnumerable<T> implementa el IEnumerable no genérico, puede simplemente convertirlo en eso.

// Does write handle null? Might need some sanity aswell. 

var enumerable = variable as System.Collections.IEnumerable; 

if (enumerable != null) 
    foreach(var item in enumerable) 
     Write(item); 
else 
    Write(item);  
+0

Parece que puede ser la mejor respuesta en realidad. – Earlz

+0

Cambié la respuesta porque terminé usando este método, que en mi opinión es mucho más limpio. – Earlz

+0

Además, para evitar el error Mono mencionado a continuación, tuve que convertir 'variable' a un' objeto' primero. – Earlz

16

Si desea realizar una prueba para el IEnumerable no genérico, deberá incluir una directiva using System.Collections en la parte superior del archivo de origen.

Si desea probar para una IEnumerable<T> de algún tipo, entonces tendrá algo como esto en su lugar:

if (variable != null) 
{ 
    if (variable.GetType().GetInterfaces().Any(
      i => i.IsGenericType && 
      i.GetGenericTypeDefinition() == typeof(IEnumerable<>))) 
    { 
     // foreach... 
    } 
} 
+0

Ya tengo ese uso en la parte superior de mi archivo fuente. – Earlz

+0

@Earlz 'System.Collections.Generic'!= 'System.Collections' - el error en la publicación es indicativo de no encontrar el tipo no genérico (IEnumerable). –

+0

Heh, utilicé esto y Mono me dio una bofetada con 'Código de IL no válido en EViewEngine.TestView: BuildOutput(): IL_0105: castclass 0x1b000002' Hmm eso es interesante. – Earlz

2

En general, , sin no genérico tipo base/interfaz, esto requiere GetType y una búsqueda recursiva a través de los tipos/interfaces básicos.

Sin embargo, que no se aplica aquí :-) sólo tiene que utilizar el non-generic IEnumerable (System.Collections.IEnumerable), de la que el generic IEnumerable (System.Collections.Generic.IEnumerable<T>) hereda.

1

Bueno, algo simple, pero ... si sólo tiene:

using System.Collections.Generic; 

puede que tenga que añadir:

using System.Collections; 

El primero define IEnumerable<T> y última define IEnumerable.

14

Las otras respuestas han señalado la diferencia IEnumerable genérica/no genérica, pero también debo señalar que también querrá probar específicamente para String porque implementa IEnumerable pero dudo que desee tratarlo como una colección de personajes.

0

Ésta es una vieja pregunta, pero yo quería mostrar un método alternativo para determinar si un SomeType es IEnumerable:

var isEnumerable = (typeof(SomeType).Name == "IEnumerable`1"); 
0

En realidad se puede probar la clase de base de cualquier tipo genérico directamente.

instance.GetGenericTypeDefinition() == typeof(IEnumerable<>) 
Cuestiones relacionadas