2012-04-23 10 views
7

IQueryable < T> sourceがあり、動的にIQueryableをコールしたい。< T> .Count()。任意のIQueryableのCount()LINQ拡張メソッドのMethodInfoを取得する<T>

私はIQueryableで宣言されたCountメソッドのMethodInfoが必要です。

これは(のIQueryable <中>)その署名であるMSDNから:

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

これは私が得たどのくらいです:

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

が、私のマイルは常にnullです。

私も試してみました:

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

が、再びヌルを。

私の最終目標は次のようになります。

Expression.Call(mi, expr); 

UPDATE:

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

と、これは動作しますが、この和の方法は一般的なではありません: これは私が合計拡張メソッドを取得する方法です。それは静的ですが。

答えて

8

IQueryable<T>タイプの包括的な議論を解読し、それを使用する必要があります。また、メソッドを所有する型はIQueryable<T>ではなく、それはQueryableです - あなたはそれについて考えるならば、インターフェイスは静的メソッドを持つことができません(コメント者が指摘したように、C#です)。また

、それはあなたが試した方法でパラメータを一致させることができない一般的な方法だから:あなたはジェネリック型に定義IQuerable<TSource>渡す必要があるため - ないジェネリックタイプIQueryable<int>または何を実際の表現はです。

代わりに、あなただけのQueryableタイプの「カウント」と呼ばれる静的メソッドのシングルparameteredバージョンを探すことができます。

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' 

アップデート2017年3月7日 - 明らかに、何かが枠組みに変更コードサンプルの元のバージョンが動作しなくなりました。これは動作するはずの更新版です

もう少し具体的には、次のようになります。

パラメータタイプは IQueryable<TSource>がある一方で
public static int Count<TSource>(
    this IQueryable<TSource> source 
) 

だから、TSource種類以上の一般的なのです - ので、あなたのIQueryable<TSource>式に魚と、それは一般的な引数の取得する必要があり理由。また、ここでパラメータの意味を知ることができます。

+0

ありがとう、ありがとう。私はそれを試してみます。 –

+0

私は試しましたが、まだヌルです: タイプtype = expr.Type.GetGenericArguments()[0]; MethodInfo mi = typeof(クエリ可能).GetMethod( "Count"、BindingFlags.Static | BindingFlags.Public、null、new [] {type}、null); しかし、私が正しく理解していれば、この最後の関数は、私が4番目の引数として提供した型を返すはずですか? –

+0

@MilosMijatovic私の最初の答えは*かなり*正しく更新されていません –

2

コンパイラにメソッドを渡させてください。

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

私は式を試してみましょうcountEx = Expression.Call(propEx、mi);それは私にエラーを与える:静的メソッドはnullインスタンスを必要とし、非静的メソッドは非nullインスタンスを必要とする。 パラメータ名:instance – Roman

+1

MethodInfoを最初のパラメータとして使用するオーバーロードを使用します(https://msdn.microsoft.com/en-us/library/dd323922%28v=vs.110%29.aspx) System.Linq.Queryableクラスの静的な拡張メソッド;) – MBoros

+0

Cheeeeeers !!今それは動作します!ありがとう兄貴!私は答えとしてこれを好むだろう。なぜなら、これは私にはもっとはっきりしているからだ。 – Roman

関連する問題