2012-04-23 9 views
7

Tengo IQueryable < T> source y quiero llamar dinámicamente a IQueryable < T> .Count().Obtener MethodInfo de Count() Método de extensión LINQ en arbitrario IQueryable <T>

Por lo tanto, necesito MethodInfo del método Count declarado en IQueryable.

este es su firma (en IQueryable <>) de MSDN:

public static int Count<TSource>(
    this IQueryable<TSource> source 
) 

Esto es lo lejos que me dieron:

Expression expr; //this is expression which holds my IQueryable<T> 
MethodInfo mi = expr.Type.GetMethod("Count", BindingFlags.Static | BindingFlags.Public, null, new[] { expr.Type }, null); 

pero mi mi siempre es nulo;

También probé:

mi = typeof(IQueryable<>).GetMethod("Count", BindingFlags.Static | BindingFlags.Public, null, new[] { expr.Type }, null); 

pero de nuevo nula.

Mi objetivo final sería:

Expression.Call(mi, expr); 

ACTUALIZACIÓN: esto es cómo consigo método de la suma de Extensión:

MethodInfo sum = typeof(Queryable).GetMethod("Sum", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(IQueryable<decimal>) }, null); 

y esto funciona, pero este método no es Suma genérico. Es aunque estático.

Respuesta

8

Debe descifrar el argumento genérico del tipo IQueryable<T> y usar eso; también el tipo que posee el método no es IQueryable<T>, es Queryable - si lo piensas - las interfaces no pueden tener métodos estáticos (bueno, como ha señalado un comentarista, en C# eso) :).

Además, debido a que es un método genérico que no puede coincidir con los parámetros en la forma en que haya probado: porque hay que pasar el tipo genérico definiciónIQuerable<TSource> - no un genérico tipoIQueryable<int> o lo que sea la expresión real es

En su lugar puede simplemente buscar una versión de un solo parametrizado de un método estático denominado 'conde' del tipo Queryable:

Type genericArgument = expr.GetGenericArguments()[0]; 

MethodInfo countMethod = typeof(Queryable) 
       .GetMethods(BindingFlags.Static | BindingFlags.Public) 
       //narrow the search before doing 'Single()' 
       .Single(mi => mi.Name == "Count" 
         // this check technically not required, but more future proof 
         && mi.IsGenericMethodDefinition 
         && mi.GetParameters().Length == 1) 
       .MakeGenericMethod(genericArgument); 

//now you can bind to 'countMethod' 

actualización 7 º de marzo de 2017 - Es evidente que algo cambió en el marco que detuvo la ejecución de la versión original del ejemplo de código - esta es una versión actualizada que debería funcionar

Yendo un poco más allá - la firma del método es:

public static int Count<TSource>(
    this IQueryable<TSource> source 
) 

Así, mientras que el tipo de parámetro es IQueryable<TSource> es genérico sobre el tipo TSource - de ahí la razón por la que necesita para pescar en su IQueryable<TSource> expresión y agarrar su argumento genérico. Y también debería ser capaz de ver lo que quiero decir sobre el parámetro aquí.

+0

Ok, gracias. Lo intentaré. –

+0

Lo intenté, pero sigue siendo nulo: Tipo type = expr.Type.GetGenericArguments() [0]; MethodInfo mi = typeof (Queryable) .GetMethod ("Count", BindingFlags.Static | BindingFlags.Public, null, new [] {type}, null); Pero, si entiendo correctamente, esta última función debería devolver algo sea cual sea el (los) tipo (s) que proporciono como el cuarto argumento, ¿verdad? –

+0

@MilosMijatovic mi respuesta inicial no fue * bastante * correcta, actualizó –

2

Deje que el compilador obtenga el método para usted.

Type genericArgument = expr.GetGenericArguments()[0]; 
var fakeExp = (Expression<Func<IQueryable<int>, int>>)(q => q.Count()); 
var mi = ((MethodCallExpression)fakeExp.Body).Method.GetGenericMethodDefinition().MakeGenericMethod(genericArgument); 
+0

Cuando intento Expresión countEx = Expression.Call (propEx, mi); me da error: el método estático requiere una instancia nula, el método no estático requiere una instancia no nula. Nombre del parámetro: instancia – Roman

+1

Utilice la sobrecarga que toma el MethodInfo como el primer parámetro (https://msdn.microsoft.com/en-us/library/dd323922%28v=vs.110%29.aspx) Count is a método de extensión estático en la clase System.Linq.Queryable;) – MBoros

+0

Cheeeeeers !! ¡Ahora funciona! ¡Gracias hermano! Preferiría esto como una respuesta, porque esta es más clara para mí. – Roman

Cuestiones relacionadas