2

给定以下方法签名:

string GetActionName<TController, T1, TResult>(Expression<Func<TController, Func<T1, TResult>>> expression)

如何从以下实现中获取方法名称:

GetActionName<EventsController, int, IEnumerable<EventDto>>(c => c.GetEventsByIdLocation);

哪里GetEventsById有签名:

IEnumerable<EventDto> GetEventsByIdLocation(int id)

我目前的尝试给了我一个例外:

无法将“System.Linq.Expressions.InstanceMethodCallExpressionN”类型的对象转换为“System.Linq.Expressions.MemberExpression”类型。

var convertExpression = (UnaryExpression)expression.Body;
var memberExpression = (MemberExpression)convertExpression.Operand;
return memberExpression.Member.Name;

在此处输入图像描述

4

1 回答 1

5

主要问题是在您的调用中,您实际上并没有调用该方法,而是返回它。这导致表达式树包含对名为 的方法的调用CreateDelegate。一旦我们有了它,我们methodCallExpression就需要提取对象,并读取它的值,这就是你的方法。

免责声明:在我认为与您的情况相同的情况下,这对我有用。但是,如果它是解决我不知道的更大问题的最佳方法。它似乎相当缓慢。

var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var constantExpression = (ContantExpression)methodCallExpression.Object;
var methodInfo = (MethodInfo)constantExpression.Value;
return methodInfo.Name

另一种选择是提供对该方法的实际方法调用,如下所示:

GetActionName<EventsController, IEnumerable<EventDto>>(
    c => c.GetEventsByIdLocation(0));

这将要求您将方法更改为:

string GetActionName<TController, TResult>(
    Expression<Func<TController, TResult>> expression)
{
    return ((MethodCallExpression)expression.Body).Method.Name;
}

此解决方案可能会执行得更快。尽管我没有做过任何基准测试或任何事情。此外,此选项不会将您限制为只能获取采用一个 int 参数的方法的名称。

于 2013-06-06T17:29:59.370 回答