从Expression获取方法名称

时间:2013-06-06 17:25:56

标签: c# lambda type-conversion

给出以下方法签名:

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;

enter image description here

1 个答案:

答案 0 :(得分: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参数的方法的名称。