簡體   English   中英

Lambda的Linq表達式:明確指定參數

[英]Linq Expression from Lambda: specify parameter explicitly

我想嵌入一個表達式樹,例如

Expression<Func<MyObject, double>> expr = (o) => o.Value;

解析器生成的更大的表達式樹。 但是,參數o已在外部表達式樹內部定義。 原則上,我將必須搜索expr的主體,並用解析的表達式樹中的實例替換所有出現的參數。

有內置的方法可以做到這一點嗎? 還是有一種方法可以在預先指定參數實例的同時直接生成lambda表達式?

您不能直接指示編譯器重用您現有的ParameterExpression實例,但是之后絕對可以替換它們(實際上是創建新的表達式樹)。

內置的ExpressionVisitor在繁重的工作中大有幫助; 它是您可以添加所需功能的無操作訪客。 在這種情況下,您需要指示它替換ParameterExpression實例,因此您可以這樣做:

// Sorry for the atrocious formatting, wanted to keep it scrollbar-free
class ParameterReplacementVisitor : ExpressionVisitor
{
    private readonly
    IEnumerable<KeyValuePair<ParameterExpression, ParameterExpression>>
    replacementMap;

    public ParameterReplacementVisitor(
        IEnumerable<KeyValuePair<ParameterExpression, ParameterExpression>> map)
    {
        this.replacementMap = map;
    }

    protected override Expression VisitLambda<T>(Expression<T> node)
    {
        return Expression.Lambda<T>(
            Visit(node.Body),
            node.Parameters.Select(Visit).Cast<ParameterExpression>());
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        var replacement = this.replacementMap
                              .Where(p => p.Key == node)
                              .DefaultIfEmpty()
                              .First().Value;
        return base.VisitParameter(replacement ?? node);
    }
}

您可以這樣使用:

Expression<Func<int, bool>> e1 = i => true;
Expression<Func<int, bool>> e2 = j => false;

Console.WriteLine(e1.Parameters[0] == e2.Parameters[0]); // false

var replacements = new Dictionary<ParameterExpression, ParameterExpression>
{
    { e1.Parameters[0], e2.Parameters[0] }
};

var replacer = new ParameterReplacementVisitor(replacements);
var e3 = replacer.VisitAndConvert(e1, "replacing parameters");

Console.WriteLine(e3.Parameters[0] == e2.Parameters[0]); // true

暫無
暫無

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

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