构建将两个函数组合为复合函数的表达式树
本文关键字:组合 复合函数 表达式 函数 两个 构建 | 更新日期: 2023-09-27 17:58:12
我得到了以下内容:
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)
或者希望更整洁,但这将是一个开始
有没有一种方法可以将编译后的函数反编译回表达式?
有没有一种方法可以将编译后的函数反编译回表达式?
不,至少不容易。您必须解释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);
您可以使用表达式访问者通过参数替换来实现这一点。这应该会告诉您需要了解的内容:http://www.codeproject.com/Articles/143096/Parameter-Substitution-within-Expression-Trees
使用Thomas Levsque的访问者实现,可以推广单参数lambda组合。
public static Expression<Func<TSource, TFinal>>
CompositeExpression<TSource, TInner, TFinal>
(
this Expression<Func<TInner, TFinal>> outerlambda,
Expression<Func<TSource, TInner>> innerlambda)
{
var visitor = new ParameterReplacementVisitor(outerlambda.Parameters[0], innerlambda.Body);
var expandedOuter = visitor.Visit(outerlambda.Body);
var composite =
Expression.Lambda<Func<TSource, TFinal>>(
expandedOuter,
innerlambda.Parameters);
return composite;
}