是否可以将委托实例强制转换为Lambda表达式?

时间:2009-01-21 13:35:43

标签: c# lambda resharper expression-trees

这是我的问题的背景:

一种常见的技术是将方法的参数声明为Lambda表达式而不是委托。这样该方法可以检查表达式以执行有趣的操作,例如在委托实例的主体中找出方法调用的名称。

问题是你失去了Resharper的一些智能功能。如果方法的参数被声明为委托,Resharper会在写入此方法的调用时提供帮助,并提示您使用x => x语法,作为此方法的参数值。

所以......回到我的问题,我想做以下几点:

    MethodThatTakesDelegate(s => s.Length);
}

private void MethodThatTakesDelegate(Func<string, object> func)
{
    //convert func into expression
    //Expression<Func<string, object>> expr = "code I need to write"

    MethodThatTakesExpression(expr);
}


private void MethodThatTakesExpression(Expression<Func<string, object>> expr)
{
    //code here to determine the name of the property called against string (ie the Length)
}

3 个答案:

答案 0 :(得分:2)

你正在使用术语“lambda表达”的任何地方你实际上是指“表达式树”。

lambda表达式是源代码中的位

parameters => code

e.g。

x => x * 2

表达式树是System.Linq.Expressions.Expression类(或者更确切地说是派生类之一)的实例,它们将代码表示为数据。

编译器将Lambda表达式转换为 表达式树(或者更确切地说,是在执行时生成表达式树的代码)委托实例。

你可以将LambdaExpression的实例(这是Expression的子类之一)编译成一个委托,但你不能反过来。

理论上可能可能基于MethodBase.GetMethodBody某些情况下返回的IL编写这样的“反编译器”,但目前有各种各样的无法用表达式树表示的代理。表达式树代表表达式而不是语句或语句块 - 因此没有循环,分支(条件除外),赋值等。我相信这可能会在.NET中发生变化4.0,虽然我不希望微软的反编译步骤,除非有一个非常好的理由。

答案 1 :(得分:0)

我不相信你可以在这里实现你想要的。从代码中的注释看起来,您试图捕获在MethodThatTakesExpression中执行赋值的属性的名称。这需要一个表达式lambda表达式,它捕获属性访问的上下文。

在您将委托传递给MethodThatTakesDelegate时,此上下文将丢失。代理只存储方法地址而不存储有关方法信息的任何上下文。一旦进行了这种转换,就无法将其恢复。

为什么不可能这样做的一个例子是甚至可能没有支持委托的命名方法。可以使用ReflectionEmit生成一个没有任何名称且仅存在于内存中的方法。虽然可以将其分配给Func对象。

答案 2 :(得分:0)

不,这是不可能的。