2012-04-23 15 views
7

I ho IQueryable < T> source e voglio chiamare IQueryable < T> .Count().Ottieni MethodInfo of Count() metodo di estensione LINQ su arbitrario IQueryable <T>

Quindi, ho bisogno di MethodInfo del metodo Count dichiarato in IQueryable.

questa è la sua firma (in IQueryable <>) da MSDN:

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

Questo è quanto ho ottenuto:

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); 

ma il mio mi è sempre nullo;

Ho anche provato:

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

ma ancora nulla.

Il mio obiettivo finale sarebbe:

Expression.Call(mi, expr); 

UPDATE: questo è come ottengo metodo Sum Estensione:

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

e questo funziona, ma questo metodo Sum non è generica. È statico.

risposta

8

È necessario eliminare l'argomento generico del tipo IQueryable<T> e utilizzarlo; anche il tipo che possiede il metodo non è IQueryable<T>, è Queryable - se ci pensate - le interfacce non possono avere metodi statici (beh, come ha sottolineato un commentatore, in C# che è) :).

Inoltre, poiché si tratta di un metodo generico non si può corrispondere ai parametri nel modo in cui hai provato: perché è necessario passare il tipo generico definizioneIQuerable<TSource> - non un generico tipoIQueryable<int> o qualsiasi altra cosa l'espressione attuale è.

Invece si può solo cercare una versione single-parametrato di un metodo statico chiamato 'Count' 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' 

Aggiornamento 7 marzo 2017 - Chiaramente, qualcosa è cambiato nel quadro che fermò la versione originale del codice di esempio da lavoro - si tratta di una versione aggiornata che dovrebbe funzionare

Andando in esso un po 'oltre - la firma del metodo è:

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

Così, mentre il tipo di parametro è IQueryable<TSource> è generico rispetto al tipo TSource - da qui il motivo per cui è necessario pescare nel vostro IQueryable<TSource> espressione e afferrare è argomento generico. E dovresti anche essere in grado di vedere cosa intendo riguardo il parametro qui.

+0

Ok, grazie. Lo proverò. –

+0

L'ho provato ma è ancora nullo: Tipo type = expr.Type.GetGenericArguments() [0]; MethodInfo mi = typeof (Queryable) .GetMethod ("Count", BindingFlags.Static | BindingFlags.Public, null, new [] {type}, null); Ma, se ho capito bene, questa ultima funzione dovrebbe restituire qualcosa qualunque tipo (s) fornisco come quarto argomento, giusto? –

+0

@MilosMijatovic la mia risposta iniziale non era * abbastanza * giusto aggiornato –

2

Lascia che il compilatore prenda il metodo per te.

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

Quando provo Espressione countEx = Expression.Call (propEx, mi); mi dà errore: il metodo statico richiede un'istanza nulla, il metodo non statico richiede un'istanza diversa da null. Nome parametro: istanza – Roman

+1

Utilizzare il sovraccarico che utilizza MethodInfo come primo parametro (https://msdn.microsoft.com/en-us/library/dd323922%28v=vs.110%29.aspx) Count è un metodo di estensione statica nella classe System.Linq.Queryable;) – MBoros

+0

Cheeeeeers !! Ora funziona! Grazie, fratello! Preferirei che fosse una risposta, perché questo è più chiaro per me. – Roman

Problemi correlati