Is there a way to decompiled a compiled function back to an expression?
No, at least not an easy one. You would have to interprete the IL code and translate it back.
You can combine your two functions like this:
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);
Which would give you something like (r, h) => cubed (XTCylinderVolume (r, h))
.
It's not exactly what you asked, but it's functionally equivalent.
If you want to actually expand the function, it's a bit harder... You need to visit the expression tree of cubed
and replace the parameter with the body of XTCylinderVolume
.
It can be done by implementing an expression visitor:
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);
}
}
Which you can then use like this:
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);