簡體   English   中英

LINQ表達式定義為lambda表達式是否包含其他LINQ表達式?

[英]Can a LINQ Expression defined as a lambda expression include other LINQ Expressions?

使用LINQ表達式時,C#編譯器可以方便地將C#lambdas轉換為Expression對象:

//using System;
//using System.Linq.Expressions;

Expression<Func<int, bool>> lambda_expression = (int x) => x == 3;

這很方便,與顯式構建表達式相比可以節省大量的輸入:

Expression<Func<int, bool>> explicit_expression_object;
{
    var x = Expression.Parameter(typeof(int), "x");
    explicit_expression =
        Expression.Lambda<Func<int, bool>>(Expression.Equal(x, Expression.Constant(3)), x);
}

但是,有些情況下需要使用“longhand”Expression對象語法,例如在運行時動態創建表達式時。 因此,我目前發現自己使用“表達式lambdas”和動態生成的“顯式”表達式對象的混合。

是否可以將Expression對象“包含”或“嵌入”到表達式lambda中?

例如:

Expression inner_expression_object = Expression.Constant(3);

Expression<Func<int, bool>> wrapper_expression =
    (int x) => x == inner_expression_object.Embed();

使用ExpressionVisitor ,可以更換一個電話Expression與擴展方法Expression

首先,您需要一個ExpressionVisitor類來將Embed方法調用擴展為它們的值:

public class EmbedVisitor : ExpressionVisitor {
    public override Expression Visit(Expression node) {
        if (node?.NodeType == ExpressionType.Call) {
            var callnode = node as MethodCallExpression;
            if (callnode.Method.Name == "Embed" && callnode.Method.DeclaringType == typeof(ExpressionExt))
                return callnode.Arguments[0].Evaluate<Expression>();
        }

        return base.Visit(node);
    }
}

那么你需要一個靜態類來擴展所需的擴展方法:

public static class ExpressionExt {
    public static T Embed<T>(this Expression e) {
        return default(T);
    }

    public static Expression ExpandEmbed(this Expression orig) => new EmbedVisitor().Visit(orig);

    public static T Evaluate<T>(this Expression e) {
        //A little optimization for constant expressions
        if (e.NodeType == ExpressionType.Constant)
            return (T)((ConstantExpression)e).Value;
        else
            return (T)Expression.Lambda(e).Compile().DynamicInvoke();
    }
}

現在您可以使用它們來擴展嵌入式Expression值子表達式:

var inner_expression_object = Expression.Constant(3);

Expression<Func<int, bool>> wrapper_expression =
    (int x) => x == inner_expression_object.Embed<int>();

var expanded = wrapper_expression.ExpandEmbed();
// Expression<Func<int,bool>> expanded == (int x) => x == 3;

您還可以直接嵌入Expression表達式並展開它們:

Expression<Func<int,bool>> wrap2 = x => x == Expression.Multiply(Expression.Constant(4), Expression.Constant(8)).Embed<int>();
var expanded2 = wrap2.ExpandEmbed();
// Expression<Func<int,bool>> expanded2 = x => x == 4*8;

暫無
暫無

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

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