无需调用即可从lambda获取方法名称

时间:2014-08-07 14:54:50

标签: c# lambda expression-trees

我希望从lambda表达式中获取方法名称,我知道可以这样做:

GetName(() => MethodA());

我的问题是如果MethodA接受任何args,你必须提供它们只是为了满足编译器关于表达式(毕竟,它怎么知道你并没有真正执行它?)< / p>

我希望能够做到:

GetName(() => MethodA);

有没有办法做到这一点?


注意:这不是重复,这是处理Method Group而不是实际的&#34;调用&#34;一种方法。

2 个答案:

答案 0 :(得分:3)

当然可以。例如,如果您使用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表达式出现在&#34;呼叫&#34;一个方法,它只是一个表达式,并且实际上不会生成对该方法的调用。
  2. 尝试以这种方式捕获方法组将很难区分具有相同名称的重载方法。
  3. 出于这个原因,我不得不想象你最好使用 涉及方法调用表达式的更传统的方法。

答案 1 :(得分:1)

对于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