表达式树ExpressionTrees
简介
表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如方法调用和 x < y 这样的二元运算等。
你可以对表达式树中的代码进行编辑和运算。这样能够动态修改可执行代码、在不同数据库中执行 LINQ 查询以及创建动态查询。
表达式树还能用于动态语言运行时 (DLR) 以提供动态语言和 .NET Framework 之间的互操作性。
一、Lambda 表达式创建表达式树
Expression<Action<int>> actionExpression = n => Console.WriteLine(n);
Expression<Func<int, bool>> funcExpression1 = (n) => n < ;
Expression<Func<int, int, bool>> funcExpression2 = (n, m) => n - m == ;
var lambda = actionExpression.Compile();
lambda();//输出11
Console.ReadLine();
二、API 创建表达式树
//通过 Expression 类创建表达式树
// lambda:num => num == 0
ParameterExpression pExpression = Expression.Parameter(typeof(int)); //参数:num
ConstantExpression cExpression = Expression.Constant(); //常量:0
BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.Equal, pExpression, cExpression); //表达式:num == 0
Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(bExpression, pExpression); //lambda 表达式:num => num == 0
var aa = lambda.Compile();
Console.WriteLine("{0}", aa()); //false
Console.WriteLine("{0}", aa()); //true
Console.ReadLine();
三、解析表达式树
Expression<Func<int, bool>> funcExpression = num => num == ; //开始解析
ParameterExpression pExpression = funcExpression.Parameters[]; //lambda 表达式参数
BinaryExpression body = (BinaryExpression)funcExpression.Body; //lambda 表达式主体:num == 0 Console.WriteLine($"解析:{pExpression.Name} => {body.Left} {body.NodeType} {body.Right}");
Console.ReadLine();
四、表达式树永久性
表达式树应具有永久性(类似字符串)。这意味着如果你想修改某个表达式树,则必须复制该表达式树然后替换其中的节点来创建一个新的表达式树。 你可以使用表达式树访问者遍历现有表达式树。
五、编译表达式树
//Expression<TDelegate> 类型提供了 Compile 方法以将表达式树表示的代码编译成可执行委托。
Expression<Func<string, int>> funcExpression = msg => msg.Length;
//表达式树编译成委托
var lambda = funcExpression.Compile();
//调用委托
Console.WriteLine(lambda("Hello, World!")); //13 //语法简化
Console.WriteLine(funcExpression.Compile()("Hello, World!")); //
Console.ReadLine();
六、执行表达式树
int n = ;
int m = ;
var p1 = Expression.Parameter(typeof(int), "num1");
var p2 = Expression.Parameter(typeof(int), "num2");
//待执行的表达式树
BinaryExpression bExpression = Expression.Add(p1, p2);
//创建 lambda 表达式
Expression<Func<int,int,int>> funcExpression = Expression.Lambda<Func<int, int, int>>(bExpression, p1, p2);
//编译 lambda 表达式
Func<int, int, int> func = funcExpression.Compile(); //执行 lambda 表达式
Console.WriteLine($"{n} + {m} = {func(n,m)}");
Console.ReadLine();
七、修改表达式树
static void Main(string[] args)
{
Expression<Func<int, bool>> funcExpression = num => num == ;
Console.WriteLine($"Source: {funcExpression}");//Source: num => (num == 0) var visitor = new NotEqualExpressionVisitor();
var expression = visitor.Visit(funcExpression); Console.WriteLine($"Modify: {expression}");//Source: num => (num != 0) Console.Read();
} /// <summary>
/// 不等表达式树访问器
/// </summary>
public class NotEqualExpressionVisitor : ExpressionVisitor
{
public Expression Visit(BinaryExpression node)
{
return VisitBinary(node);
} protected override Expression VisitBinary(BinaryExpression node)
{
//该类继承 ExpressionVisitor 类,通过 Visit 方法间接调用 VisitBinary 方法将 != 替换成 ==。基类方法构造类似于传入的表达式树的节点,但这些节点将其子目录树替换为访问器递归生成的表达式树。
return node.NodeType == ExpressionType.Equal
? Expression.MakeBinary(ExpressionType.NotEqual, node.Left, node.Right) //重新弄个表达式:用 != 代替 ==
: base.VisitBinary(node);
}
}
表达式树ExpressionTrees的更多相关文章
- 不可不知的表达式树(1)Expression初探
说起Lambda表达式,大家基本都很熟悉了,而表达式树(Expression Trees),则属于80%的工作中往往都用不到的那种技术,所以即便不是什么新技术,很多人对其理解都并不透彻.此文意图从表达 ...
- ASP.NET Core中使用表达式树创建URL
当我们在ASP.NET Core中生成一个action的url会这样写: var url=_urlHelper.Action("Index", "Home"); ...
- LINQ Expresstion Tree 表达式树
Expression trees represent code in a tree-like data structure, where each node is an expression, for ...
- 表达式树(Expression Trees)
[翻译]表达式树(Expression Trees) 原文地址:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/con ...
- 表达式树(Expression Tree)
饮水思源 本文并非原创而是下面网址的一个学习笔记 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/e ...
- 再讲IQueryable<T>,揭开表达式树的神秘面纱
接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...
- [C#] C# 知识回顾 - 表达式树 Expression Trees
C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...
- 轻量级表达式树解析框架Faller
有话说 之前我写了3篇关于表达式树解析的文章 干货!表达式树解析"框架"(1) 干货!表达式树解析"框架"(2) 干货!表达式树解析"框架" ...
- 用五分钟重温委托,匿名方法,Lambda,泛型委托,表达式树
这些对老一代的程序员都是老生常谈的东西,没什么新意,对新生代的程序员却充满着魅力.曾经新生代,好多都经过漫长的学习,理解,实践才能掌握委托,表达式树这些应用.今天我尝试用简单的方法叙述一下,让大家在五 ...
随机推荐
- bzoj千题计划298:bzoj3997: [TJOI2015]组合数学
http://www.lydsy.com/JudgeOnline/problem.php?id=3997 最小链覆盖=最长反链长度 所以题目等价于寻找一条从右上角到左下角的最长路 #include&l ...
- Centos7更改yum镜像源
1. 备份本地yum源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak 2.获取阿里yum源配置文 ...
- Javaweb学习笔记——(六)——————xml中jaxp两种解析方式和dom4j运用
1.xml的scheam约束 dtd的语法:<!ElEMENT 元素名称 约束> **schema符合xml的语法,xml语句 **一个xml中可以有多个schema,多个schema使用 ...
- 拆分窗口QSplitter
拆分窗口中可以添加许多子控件,各个子控件通过拆分线相互分隔开来,拖动该拆分线可以随意改变子控件大小 import sys from PyQt5.QtCore import Qt from PyQt5. ...
- luogu P4036 [JSOI2008]火星人
传送门 很久以前xzz大佬就喊我做这题,结果现在才做qwq 因为要在序列中插入,所以直接用\(Splay\)维护这个串的哈希值,插入就直接把那个点插♂进去,修改就把点旋到根,然后修改和pushup,询 ...
- (原创 开源)AppWidge的使用—桌面便利贴
Android平台的一大特色就是支持桌面插件——AppWidget. 且不说,AppWidget是否会影响系统的流畅性,AppWidget确实是满足了用户个性化和快捷操作的需要. 常见的AppWidg ...
- History API:ScrollRestoration
By Paul Lewis(设计和性能倡导者) 翻译:江天 使用history api管理url是非常棒的一件事,可以说这是一个好web app的极为重要的特点.但它有一个缺点,滚动位置虽然被存储 ...
- Mybatis进阶学习笔记——关系查询——一对一查询
用户和订单的需求 通过查询订单,查询用户,就是一对一查询 (1)自定义JavaBean(常用,推荐使用) <select id="queryOrderUser" result ...
- IDEA常用快捷键[转]
原文:http://www.cnblogs.com/wxdlut/p/3410541.html 查询快捷键CTRL+N 查找类CTRL+SHIFT+N 查找文件CTRL+SHIFT+ALT+N ...
- jquery 操作表单的问题
下拉框获取选中项的值: $("#ID").find("option:selected").val(); 设置下拉框选中项: $("#ID") ...