2

これは重複していると確信していますが、答えが見つかりません。

System.Linq.Queryable次のシグネチャを持つメソッドがあります。

public static int Count<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, bool>> predicate);

System.Type::GetMethodメソッドを使用してこのメ​​ソッドを取得するにはどうすればよいですか?

typeof(System.Linq.Queryable).GetMethod("Count", type[]{ ??? });
4

2 に答える 2

1

あなたが使用することができます

var method = typeof (System.Linq.Queryable).GetMethods().Single(a=>a.Name == "Count" && a.GetParameters().Length == 2);

その後、呼び出したい場合は

method.MakeGenericMethod(typeof (YourType));

さらに、フィルタリングすることもできます(さまざまな選択のために):

var sel1 = typeof (Queryable).GetMethods().Single(a => a.Name == "Select"
                && a.MakeGenericMethod(typeof(object), typeof(object)).GetParameters()[1].ParameterType == typeof(Expression<Func<object, object>>));

var sel2 = typeof(Queryable).GetMethods().Single(a => a.Name == "Select"
                && a.MakeGenericMethod(typeof(object), typeof(object)).GetParameters()[1].ParameterType == typeof(Expression<Func<object,int, object>>));
于 2013-10-28T18:12:11.720 に答える
1

最も手間がかからない方法は、おそらく、必要なメソッドを式ツリーでキャプチャしてから、メソッド参照を見つけるために掘り下げます。これを 1 回実行してジェネリック メソッド定義を取得し、結果をキャッシュして、必要に応じて再利用できます。

Expression<Func<IQueryable<int>, int>> getCount = p => p.Count();
MethodInfo countMethod = ((MethodCallExpression)getCount.Body).Method.GetGenericMethodDefinition();

これには、 API の変更 (より多くの "Count" メンバーの追加など) に対してある程度回復力があるという利点があります。返されるメソッドは、コンパイル時に式がバインドされるメソッドになります。

必要に応じて、この動作をユーティリティ メソッドに抽出できます。

public static MethodInfo MethodOf(Expression<Action> accessExpression, bool dropTypeArguments = false)
{
    if (accessExpression == null)
        throw new ArgumentNullException("accessExpression");

    var callExpression = accessExpression.Body as MethodCallExpression;
    if (callExpression == null)
        throw new ArgumentException("Expression body must be a method call.", "accessExpression");

    var method = callExpression.Method;

    if (dropTypeArguments && method.IsGenericMethod)
        return method.GetGenericMethodDefinition();

    return method;
}

public static MethodInfo MethodOf<TInstance>(Expression<Action<TInstance>> call, bool dropTypeArguments = false)
{
    if (call == null)
        throw new ArgumentNullException("call");

    var callExpression = call.Body as MethodCallExpression;
    if (callExpression == null)
        throw new ArgumentException("Expression body must be a method call.", "call");

    var method = callExpression.Method;

    if (dropTypeArguments && method.IsGenericMethod)
        return method.GetGenericMethodDefinition();

    return method;
}

静的スタイルの呼び出しには最初のオーバーロードを使用し、インスタンス スタイルの呼び出しには後者を使用します。

var countMethod1 = Extensions.MethodOf(() => Queryable.Count(default(IQueryable<int>)), dropTypeArguments: true);
var countMethod2 = Extensions.MethodOf((IQueryable<int> p) => p.Count(), dropTypeArguments: true);

型引数を保持するには (たとえば、Count<int>()の代わりに解決するにはCount<T>())、単に引数を省略するdropTypeArguments: trueか、 に設定しfalseます。

これらはそれほど包括的ではないことに注意してください。たとえば、宣言型のジェネリック パラメーターをドロップしません (メソッド自体のみ)。自由に使用、拡張、または破棄してください:)。

于 2013-10-28T18:12:49.893 に答える