c# - 构建将两个函数组合成一个复合函数的表达式树

标签 c# lambda tree expression composite

我得到了以下信息:

 Expression<Func<double, double, double>> XTCylinderVolume =
                (r, h) => 3.14  * r * r * h;
 Expression<Func<double, double>> cubed =    (V) => V  * V * V ;

我可以将它们结合起来构建一个复合函数,称之为 fgCompiled

 var cubedC = cubed.Compile();
 Func<double, double, double> fgComplied = (r, h) => cubedC(XTCylinderVolume.Compile()(r, h));

  fgCompiled(2,1)  
 //answer = 1981.385..;

如何获得未编译的表达式 fg,以便 fg.ToString() 看起来像

=> (3.14 * r * r * h ) * ( 3.14 * r * r * h ) * (3.14 * r * r * h)  

或者希望更整洁,但这将是一个开始。
有没有办法将已编译的函数反编译回表达式?

最佳答案

Is there a way to decompiled a compiled function back to an expression?

不,至少不是一件容易的事。您将不得不解释 IL 代码并将其翻译回来。

你可以像这样组合你的两个函数:

 var pr = Expression.Parameter(typeof(double), "r");
 var ph = Expression.Parameter(typeof(double), "h");
 Expression<Func<double, double, double>> fgCompiled =
    Expression.Lambda<Func<double, double, double>>(
        Expression.Invoke(
            cubed,
            Expression.Invoke(
                XTCylinderVolume,
                pr, ph)),
        pr, ph);

这会给你类似 (r, h) => cubed (XTCylinderVolume (r, h)) 的东西。

这与您的要求不完全相同,但在功能上是等效的。

如果要真正扩展功能,有点难...需要访问cubed的表达式树,将参数替换为XTCylinderVolume.

这可以通过实现一个表达式访问者来完成:

class ParameterReplacementVisitor : ExpressionVisitor
{
    private readonly ParameterExpression _paramToReplace;
    private readonly Expression _replacementExpression;
    public ParameterReplacementVisitor(ParameterExpression paramToReplace, Expression replacementExpression)
    {
        _paramToReplace = paramToReplace;
        _replacementExpression = replacementExpression;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        if (node == _paramToReplace)
            return _replacementExpression;
        return base.VisitParameter(node);
    }
}

然后你可以像这样使用它:

var visitor = new ParameterReplacementVisitor(cubed.Parameters[0], XTCylinderVolume.Body);
var expandedBody = visitor.Visit(cubed.Body);

var fgCompiled = 
    Expression.Lambda<Func<double, double, double>>(
        expandedBody,
        XTCylinderVolume.Parameters);

关于c# - 构建将两个函数组合成一个复合函数的表达式树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23032277/

相关文章:

r - 部分匹配字符串的最佳cutree

c# - DataGridView - 如何让复选框充当单选按钮?

c# - 几乎重复的单元测试

c# - 无法在 memcached 中存储复杂对象

c# - 如何使用XSD生成的类

mongodb - 用于 Lambda 的 NestJS 外部的 Mongoose 连接

java - 使用 foreach 添加重复的字符串键以进行映射,其中值是重复次数

c# - 根据属性值列出选择的对象范围

scala - 更改 Scala 案例类树中的节点

mysql - 在mysql中连接任意数量的字符串行(分层查询)