如何获取生成lambda表达式的字符串(源代码)?

时间:2011-09-01 14:44:42

标签: c# lambda tostring

(简称LISP黑客:我正在寻找C#中的LISP-quote等价物)

我正在尝试为一个有Func作为成员的类编写一个有意义的ToString方法。经验丰富的API用户可以通过setter-method设置此成员,如

myClassObject.SetFunction( (x) => x*x );

现在,当我在成员上使用ToString方法时,它只返回

System.Func<double,double>

这不是很有帮助。有用的是

"(x) => x*X"

有没有(最好的简单)方法呢?

感谢您提供任何帮助或意见。

编辑:更正了一些拼写错误

3 个答案:

答案 0 :(得分:8)

Expression<Func<double,double>> expr = x => x * x;
string s = expr.ToString(); // "x => (x * x)"

答案 1 :(得分:1)

我知道没有,因为该字符串从未进入系统,只有IL以某种方式生成并存储了引用...您需要将IL“反编译”为一些有意义的字符串......

使用CodeExpression,可以通过GenerateCodeFromExpression的实例调用CodeDomProvider,该实例具有C#/ VB / JScript的内置实现......但如果有的话,我会感到惊讶满足了你的需求......

另一种选择:使用Expression,您可以使用ToString() - 这也适用于LambdaExpression,因为这只是一个后代。

答案 2 :(得分:1)

如果您愿意将代理作为表达式存储,则可以实现您想要的目标。代码看起来像这样:

private Expression<Func<double, double>> myFunc;
private Func<double, double> cachedDelegate; 

public void SetFunc(Expression<Func<double,double>> newFunc)
{
    this.myFunc = newFunc;
    this.cachedDelegate = null;
}

public double ExecFunc(double x)
{
    if (this.myFunc != null)
    {
        if (this.cachedDelegate != null)
        {
            return this.cachedDelegate(x);
        }
        else
        {
            this.cachedDelegate = this.myFunc.Compile();
            return this.cachedDelegate(x);
        }
    }

    return 0.0;
}

public string GetFuncText()
{
    if (this.myFunc != null)
    {
        return this.myFunc.ToString();
    }
    return "";
}

为了实际使用lambda表达式,必须先编译它。将其存储在委托中意味着您只能接受一次该命中。

此外,这种方法意味着用户必须使用lambda,因为方法组不能转换为Expression<Func<>>。但这不是一个大问题,因为用户可以通过MyMethod而不是传递x => MyMethod(x)

调用代码看起来像这样:

myObject.SetFunc(x => 2*x);
Console.WriteLine(myObject.GetFuncText());

最后要注意的是,上面的示例不是线程安全的,因此如果您希望从多个线程调用这些方法,那么某种同步将是合适的。