在不调用的情况下从lambda获取方法名

本文关键字:lambda 获取 方法 情况下 调用 | 更新日期: 2023-09-27 18:17:02

我正在寻找从lambda表达式中获得方法名称,我知道它可以这样做:

GetName(() => MethodA());

我的问题是,如果MethodA接受任何参数,你必须提供它们只是为了满足编译器对表达式的要求(毕竟,它怎么知道你没有实际执行它?)

我希望能做:

GetName(() => MethodA);

有办法做到这一点吗?


注意:这不是重复的,这是在处理Method Group,而不是对方法的实际"调用"。

在不调用的情况下从lambda获取方法名

当然可以。例如,如果你的GetName方法将Expression<Func<Action>>作为参数,那么你可以将() => MethodA传递给它,只要MethodA可以转换为与Action相同的委托签名。

void Main()
{
    Expression<Func<Action>> x = () => Foo;
    Expression<Func<Func<int>>> y = () => Foo2;
    var xName = ((MethodInfo)((ConstantExpression)((MethodCallExpression)((UnaryExpression)x.Body).Operand).Object).Value).Name;
}
void Foo(){}
int Foo2(){return 0;}

您可以编写GetName方法来检查给定的表达式并从中提取出方法组的名称。然而,有两件事你应该记住。

  1. 即使你的lambda表达式看起来"调用"了一个方法,它也只是一个表达式,实际上不会生成对该方法的调用。
  2. 试图以这种方式捕获方法组将使区分具有相同名称的重载方法变得非常困难。

出于这个原因,我不得不想象您最好使用更传统的方法包含方法调用表达式。

对于void返回的无参数方法,GetName的签名可能如下所示:

string GetName(Expression<Func<Action>> methodExpression)

Action在这里有一个问题,为了使它对其他签名的方法工作,你需要为其他委托类型添加大量的重载。

解决方案是使GetName泛型,并让用户指定委托类型:

string GetName<T>(Expression<Func<T>> methodExpression)
…
GetName<Action>(() => MethodA)

这种方法的问题是T可以是任何类型,而不仅仅是一个委托,所以很容易错误地调用这个版本的GetName,特别是由于类型推断,GetName(() => MethodB())经常会编译(特别是当MethodB返回一些东西时)。

类型约束在这里没有帮助,你不能写where T : Delegate

相关文章: