0

这是我的问题的上下文:

一种常见的技术是将方法的参数声明为 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)
}
4

3 回答 3

2

在您使用术语“lambda 表达式”的任何地方,您实际上的意思是“表达式树”。

lambda 表达式是源代码中的位,它是

parameters => code

例如

x => x * 2

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

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

您可以将LambdaExpression(它是 Expression 的子类之一)的实例编译为委托,但不能反过来。

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

于 2009-01-21T15:01:50.140 回答
0

我不相信有可能在这里实现你想要的。从代码中的注释看来,您正试图捕获在 MethodThatTakesExpression 中进行分配的属性的名称。这需要一个表达式树 lambda 表达式来捕获属性访问的上下文。

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

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

于 2009-01-21T14:12:35.967 回答
0

不,这是不可能的。

于 2009-01-21T14:15:56.880 回答