3

次のコードを考えると、

    public T Execute<T>(Func<T> methodParam)
    {
        return methodParam ();
    }

    public void CallMethodsAnonymously<T>()
    {
        T result =  Execute(() => _service.SomeMethod1());
        T result1 = Execute(() => _service.SomeMethod2(someParm1));
        T result2 = Execute(() => _service.SomeMethod3( someParm1, someParm2));
    }

Execute メソッドから、「methodParam」を調べて、無名関数本体内のパラメーターの数を抽出または決定することはできますか? たとえば、Execute メソッド内から someParam1 と someParam2 の値を決定することは可能ですか?

4

4 に答える 4

6

ExpressionAPIを使用してそれを行うことができます:

public static T Execute<T>(Expression<Func<T>> methodParam)
{
    var methodCallExpression = methodParam.Body as MethodCallExpression;
    var method = methodCallExpression.Method;
    var parameters = method.GetParameters();

    return methodParam.Compile()();
}

パラメータ変数は、ParameterInfo必要な情報を含むオブジェクトの配列になります。最後に、Compileメソッドは、実際に式を実行可能なデリゲートに変換します。C#コンパイラでは、標準のラムダ/匿名メソッドを使用して、デリゲートを受け取るメソッドを呼び出すという通常の規則を使用して、このメソッドを呼び出すこともできます。

編集:

また、someParam1とsomeParam2の実際の値を取得する方法が必要であることに気づきました。これを行う方法は次のとおりです。

private static object GetValue(Expression expression)
{
    var constantExpression = expression as ConstantExpression;
    if (constantExpression != null)
    {
        return constantExpression.Value;
    }

    var objectMember = Expression.Convert(expression, typeof(object));
    var getterLambda = Expression.Lambda<Func<object>>(objectMember);
    var getter = getterLambda.Compile();
    return getter();
}


private static object[] GetParameterValues(LambdaExpression expression)
{
    var methodCallExpression = expression.Body as MethodCallExpression;
    if (methodCallExpression != null)
    {
        return methodCallExpression.Arguments.Select(GetValue).ToArray();
    }

    return null;
}

したがって、executeメソッドで、これを行うと、次のようになります。

public static T Execute<T>(Expression<Func<T>> methodParam)
{
    var methodCallExpression = methodParam.Body as MethodCallExpression;
    var method = methodCallExpression.Method;
    var parameters = method.GetParameters();

    var values = GetParameterValues(methodParam);
    return methodParam.Compile()();
}

その場合、値は、渡されたすべての実際の値を含むobject[]になります。

于 2011-10-11T03:32:53.977 に答える
0

ありそうもない。メソッドにはデリゲートが渡されます。Executeこの場合は無名関数への参照です。あなたが求めているのは、Executeメソッドがその関数のコード内を調べて、それが何をしているのかを判断することです。

Random.Nextこれは、実行時にメソッドの内部を調べて、メソッドが呼び出すメソッドを確認しようとするのと似ています。

于 2011-10-11T03:34:16.820 に答える
0

これは質問にまったく答えていないと思います。これは実際にデリゲート メソッドを実行し、結果を values[] オブジェクトに返します。ポスターが求めていたと思いますが、デリゲート メソッド内でパラメーターの値を取得する方法も求めています。

于 2012-07-17T15:53:16.200 に答える
0

どのmethodParam呼び出しにもパラメーターはありません。
コード: () => _service.SomeMethod1() 基本的に、 を返す別の関数を「ポイント」しますT
() => _service.SomeMethod1()次と同等です。
() => { return _service.SomeMethod1(); }

実際に質問に答えるように編集します(愚かな私):
試してください:

T 結果 2 =
   実行(() =>
   {
      [ブレークポイント] return _service.SomeMethod3(someParm1, someParm2)
   }
);
于 2011-10-11T03:21:26.800 に答える