2012-04-23 8 views
7

Mam IQueryable < T> źródło i chcę dynamicznie wywoływać IQueryable < T> .Count().Uzyskaj metodę MethodInfo zliczania() LINQ na arbitralnym IQueryable <T>

Potrzebuję metody MethodInfo of Count zadeklarowanej w IQueryable.

to jest jego podpis (w IQueryable <>) z MSDN:

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

To jak daleko mam:

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

ale mój mi zawsze jest null;

Próbowałem również:

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

ale znowu zerowa.

Moim ostatecznym celem byłoby:

Expression.Call(mi, expr); 

UPDATE: to jak mam metodę Suma rozszerzenia:

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

i to działa, ale metoda ta suma nie jest nazwą rodzajową. Jest to jednak statyczne.

Odpowiedz

8

Musisz złamać ogólny argument typu IQueryable<T> i użyć go; również typ, który jest właścicielem metody, nie jest IQueryable<T>, to jest Queryable - jeśli myślisz o tym - interfejsy nie mogą mieć statycznych metod (cóż, jak zauważył komentator, w języku C#) :).

Ponadto, ponieważ jest to metoda rodzajowa nie można dopasować parametry w sposób próbowałem: ponieważ trzeba przekazać typ rodzajowy definicjęIQuerable<TSource> - nie ogólny typIQueryable<int> lub cokolwiek rzeczywiste wyrażenie jest.

Zamiast tego można po prostu spojrzeć na jeden-parametered wersji statycznej metody zwanej „Hrabia” w rodzaju 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' 

Aktualizacja 07 marca 2017 - Oczywiście, coś się zmieniło w ramach który zatrzymał oryginalną wersję przykładu kodu z działania - jest to zaktualizowana wersja, która powinna działać

Przechodząc do niej nieco dalej - sygnaturą metody jest:

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

Więc podczas gdy typ parametru jest IQueryable<TSource> to generic nad typu TSource - stąd powód dlaczego trzeba łowić w swojej wypowiedzi IQueryable<TSource> i chwycić to generic argumentem. I powinieneś także być w stanie zobaczyć, co mam na myśli o tym parametrze.

+0

Dobrze, dzięki. Spróbuję tego. –

+0

Próbowałem go, ale nadal jest pusty: Typ type = expr.Type.GetGenericArguments() [0]; MethodInfo mi = typeof (Queryable) .GetMethod ("Count", BindingFlags.Static | BindingFlags.Public, null, new [] {type}, null); Ale, jeśli dobrze rozumiem, ta ostatnia funkcja powinna zwrócić coś, co dostarczę jako czwarty argument, prawda? –

+0

@MilosMijatovic moja początkowa odpowiedź nie była * całkiem * poprawiła się –

2

Pozwól, aby kompilator uzyskał dla ciebie metodę.

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

Kiedy próbuję Expression countEx = Expression.Call (propEx, mi); daje mi błąd: metoda statyczna wymaga wystąpienia zerowego, metoda niestatyczna wymaga instancji niepustej. Nazwa parametru: instancja – Roman

+1

Użyj przeciążenia, które pobiera MethodInfo jako pierwszy parametr (https://msdn.microsoft.com/en-us/library/dd323922%28v=vs.110%29.aspx) Liczba jest metoda statycznej rozbudowy w klasie System.Linq.Queryable;) – MBoros

+0

Cheeeeeers !! Teraz działa! Dzięki stary! Wolę to jako odpowiedź, ponieważ ta jest dla mnie bardziej oczywista. – Roman

Powiązane problemy