簡體   English   中英

構建將兩個功能組合為復合功能的表達樹

[英]Building expression trees combining two functions to a composite function

我得到以下內容:

 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..;

我如何獲得未編譯的Expression 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 Levesque的visitor實現,可以對單參數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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM