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 方法实际上将 Expression 转换为可执行委托。C# 编译器还允许您使用采用委托的调用方法的常规约定以及标准 lambdas/匿名方法来调用此方法。

编辑:

我还刚刚注意到您想要一种方法来获取 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;
}

所以现在在你的执行方法中,如果你这样做:

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

methodParam任何调用都没有参数。
代码: () => _service.SomeMethod1() 基本上“指向”另一个返回T.
() => _service.SomeMethod1()相当于:
() => { return _service.SomeMethod1(); }

编辑以实际回答问题(我很傻):
尝试:

T 结果2 =
   执行(()=>
   {
      [断点]return _service.SomeMethod3(someParm1, someParm2)
   }
);
于 2011-10-11T03:21:26.800 回答
0

这不太可能。该Execute方法传递了一个委托——在这种情况下是对匿名函数的引用。您要求的是该Execute方法查看该函数的代码并确定它在做什么。

这类似于我试图Random.Next在运行时查看方法内部以查看它调用了哪些方法。

于 2011-10-11T03:34:16.820 回答
0

我认为这根本不能回答这个问题。这实际上执行了委托方法并将结果返回到 values[] 对象中。我相信发帖人在问,我也在问如何在委托方法中获取参数的值。

于 2012-07-17T15:53:16.200 回答