【Expression笔记】基础

简介

表达式树(Expression Tree):树形数据结构表示代码,以表示逻辑运算,以便可以在运行时访问逻辑运算的结构。
使用Expression<TDelegate>类型来表示表达式树
Expression对象储存了运算逻辑,它把运算逻辑保存成抽象语法树(AST),可以在运行时动态获取运算逻辑。而普通委托则没有。

使用场景

  • 根据表达式树生成sql
b.Name.Contains('范')   ->   where Name like '%范%' 
  • 动态修改表达式树

如何查看表达式树

  • 方法1、安装VS插件ExpressionTreeVisualizer(安装麻烦)
https://github.com/zspitz/ExpressionTreeVisualizer/releases
  • 方法2、安装Nuget:Install-Package ExpressionTreeToString
using System.Linq.Expressions;
using ExpressionTreeToString;

Expression<Func<Book, bool>> exp1 = b => b.Price > 5M;
Console.WriteLine(exp1.ToString("Object notation", "C#"));

输出:

var b = new ParameterExpression {
    Type = typeof(Book),
    IsByRef = false,
    Name = "b"
};

new Expression<Func<Book, bool>> {
    NodeType = ExpressionType.Lambda,
    Type = typeof(Func<Book, bool>),
    Parameters = new ReadOnlyCollection<ParameterExpression> {
        b
    },
    Body = new BinaryExpression {
        NodeType = ExpressionType.GreaterThan,
        Type = typeof(bool),
        Left = new MemberExpression {
            Type = typeof(decimal),
            Expression = b,
            Member = typeof(Book).GetProperty("Price")
        },
        Right = new ConstantExpression {
            Type = typeof(decimal),
            Value = 5
        },
        Method = typeof(decimal).GetMethod("op_GreaterThan")
    },
    ReturnType = typeof(bool)
}

动态创建表达式树

参考上面的输出内容,我们可以写代码动态构建表达式树,如下:

var b = Expression.Parameter(typeof(Book), "b");
var left = Expression.MakeMemberAccess(b,  typeof(Book).GetProperty("Price"));
var right = Expression.Constant(5M, typeof(decimal));
var body = Expression.MakeBinary(ExpressionType.GreaterThan, left, right, false, typeof(decimal).GetMethod("op_GreaterThan"));
Expression<Func<Book, bool>> exp2 = (Expression<Func<Book, bool>>)Expression.Lambda(body, b);
//测试
bool result = exp2.Compile().Invoke(new Book { Price = 10M });//true

更简单的方法构建表达式树

修改ToString参数Object notation-> Factory methods,可以直接生成构建代码:

Console.WriteLine(exp1.ToString("Factory methods", "C#"));

输出:

using static System.Linq.Expressions.Expression
var b = Parameter(
    typeof(Book),
    "b"
);
Lambda(
    MakeBinary(ExpressionType.GreaterThan,
        MakeMemberAccess(b,
            typeof(Book).GetProperty("Price")
        ),
        Constant(5), false,
        typeof(decimal).GetMethod("op_GreaterThan")
    ),
    b
);

从Lambda表达式生成表达式树

Expression<Func<Book, bool>> e1 = b =>b.Price > 5;
posted @ 2020-01-08 17:48  .Neterr  阅读(187)  评论(0编辑  收藏  举报