从Expression获取方法名称

bfl*_*mi3 2 c# lambda type-conversion

给定以下方法签名:

string GetActionName<TController, T1, TResult>(Expression<Func<TController, Func<T1, TResult>>> expression)
Run Code Online (Sandbox Code Playgroud)

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

GetActionName<EventsController, int, IEnumerable<EventDto>>(c => c.GetEventsByIdLocation);
Run Code Online (Sandbox Code Playgroud)

GetEventsById签名在哪里:

IEnumerable<EventDto> GetEventsByIdLocation(int id)
Run Code Online (Sandbox Code Playgroud)

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

无法将类型为"System.Linq.Expressions.InstanceMethodCallExpressionN"的对象强制转换为"System.Linq.Expressions.MemberExpression".

var convertExpression = (UnaryExpression)expression.Body;
var memberExpression = (MemberExpression)convertExpression.Operand;
return memberExpression.Member.Name;
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Chr*_*eld 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
Run Code Online (Sandbox Code Playgroud)

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

GetActionName<EventsController, IEnumerable<EventDto>>(
    c => c.GetEventsByIdLocation(0));
Run Code Online (Sandbox Code Playgroud)

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

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

该解决方案可能会更快地执行.虽然我没有做任何基准或任何事情.此外,此选项不会使您只能获取带有一个int参数的方法的名称.