2010-09-08 15 views
21

que necesito para ser capaz de conseguir algo similar a lo siguiente para trabajar:IQueryable OfType <T> donde T es un tipo de ejecución

Type type = ??? // something decided at runtime with .GetType or typeof; 
object[] entityList = context.Resources.OfType<type>().ToList(); 

Es esto posible? Puedo usar .NET 4 si algo nuevo en eso lo permite.

+3

¿Quieres que preguntarse por qué '?' Cuidadosamente. – leppie

+0

¿Debe ser IQueryable? Según su ejemplo, IEnumerable parece suficiente. –

+0

@leppie No entiendo su punto ... – Tablet

Respuesta

36

Se le puede llamar por la reflexión:

MethodInfo method = typeof(Queryable).GetMethod("OfType"); 
MethodInfo generic = method.MakeGenericMethod(new Type[]{ type }); 
// Use .NET 4 covariance 
var result = (IEnumerable<object>) generic.Invoke 
     (null, new object[] { context.Resources }); 
object[] array = result.ToArray(); 

Una alternativa sería escribir su propio OfTypeAndToArray método genérico de hacer las dos partes de él, pero lo anterior debe trabajar.

+0

Skeet esto funciona, qué leyenda. Solo voy a usar el perfilador de SQL para ver si está filtrando después de recuperar la colección o como parte de la consulta ... a menos usted sabe la respuesta a eso también! – Tablet

+1

@Shahin: Debería estar haciendo lo correcto: después de todo, está llamando 'Queryable.Where' en lugar de 'Enumerable.Where'. –

+0

@Skeet ¿tiene alguna idea de por qué puede estar almacenando en caché desde el primer conjunto de resultados que recibió? – Tablet

-1
object[] entityList = context.Resources 
           .Where(t=> t.GetType() == type) 
           .ToArray(); 
+0

¿No devolverá todo el contenido de los Recursos antes de ejecutar el en contra? El uso de OfType en este contexto lo ejecuta en el SQL (estoy usando Zentity) – Tablet

+0

Además de lo que dijo Shahin, esto también es incorrecto para los tipos polimórficos. – Timwi

+0

Dice que se espera el nombre del espacio de nombres cuando intento y hago eso – Tablet

8

Parece que tendrá que utilizar la reflexión aquí ...

public static IEnumerable<object> DyamicOfType<T>(
     this IQueryable<T> input, Type type) 
{ 
    var ofType = typeof(Queryable).GetMethod("OfType", 
        BindingFlags.Static | BindingFlags.Public); 
    var ofTypeT = ofType.MakeGenericMethod(type); 
    return (IEnumerable<object>) ofTypeT.Invoke(null, new object[] { input }); 
} 

Type type = // ...; 
var entityList = context.Resources.DynamicOfType(type).ToList(); 
+0

¡Gracias por su ayuda! – Tablet

0

puramente en su pregunta a uso "genéricos", No, no es posible.

Generics es una característica de tiempo de compilación, y no un descubrimiento en tiempo de ejecución. Para el tiempo de ejecución, necesita usar Reflection o Dynamic.

+2

Meh, no me gusta la caracterización de "genéricos es una función de tiempo de compilación". Es eso y también demostrablemente una característica de tiempo de ejecución (a diferencia de Java). –

+0

Puede que no te guste, pero lo importante es que los genéricos son una función de tiempo de compilación. El tipo genérico se compila con el conocimiento de la T. Si puede mostrar lo contrario, por favor, infórmeme. – Aliostad

+0

Si no fuera una característica de tiempo de ejecución, ¿cómo podría funcionar MakeGenericType? – Casey

0

qué pasa ...

public static IList OfTypeToList(this IEnumerable source, Type type) 
    { 
     if (type == null) 
      throw new ArgumentNullException(nameof(type)); 
     return 
      (IList) Activator.CreateInstance(
       typeof(List<>) 
        .MakeGenericType(type), 
       typeof(System.Linq.Enumerable) 
        .GetMethod(nameof(System.Linq.Enumerable.OfType), 
           BindingFlags.Static | BindingFlags.Public) 
        .MakeGenericMethod(type) 
        .Invoke(null, new object[] { source })); 
    } 
Cuestiones relacionadas