前言

上一篇说完了动态创建表达式树, 这篇来说一说解析表达式树.

我之所以会用到是因为最近开始大量使用 trigger 来维护冗余.

但 trigger 本身并不好维护 (EF Core 也不支持), 于是就有了自己写点简单的翻译的想法.

比如在我项目中会通过这样来表达一个冗余值

builder.HasCrossComputed(e => e.BiddingPrice, e => e.Contracts.Sum(e => e.BiddingPrice)).HasColumnName(BiddingPrice);

意思是 BiddingPrice 这个 column 是 Sum 子表的 BiddingPrice

最终会通过 EF Core Migrations 创建 3 个 trigger 监听子表的 insert, update, delete, 然后 update 父表.

主要参考

腾飞(Jesse)– 由浅入深表达式树(二)遍历表达式树

Expression Visitor

要解析表达式, 我们确实可以一层一层自己递归进去. 毕竟它是二叉树形式嘛.

但是 .NET 已经替我们做好了一个粗糙的轮子. 它叫 ExpressionVisitor

它大概长这样

public class SimpleExpressionVisitor : ExpressionVisitor
{
public class MethodCallInfo
{
public string MethodName { get; set; } = "";
public ReadOnlyCollection<Expression> Arguments { get; set; } = new ReadOnlyCollection<Expression>(new List<Expression>());
}
public List<string> VisitedMemberNames { get; set; } = new();
public List<MethodCallInfo> VisitedMethodCallInfos = new(); protected override Expression VisitMember(MemberExpression node)
{
VisitedMemberNames.Add(node.Member.Name);
return base.VisitMember(node);
} protected override Expression VisitMethodCall(MethodCallExpression node)
{
VisitedMethodCallInfos.Add(new MethodCallInfo {
MethodName = node.Method.Name,
Arguments = node.Arguments,
});
return base.VisitMethodCall(node);
}
}

玩法是这样的, ExpressionVisitor 有一个 Visit 方法. 把 expression 交给这个方法后

它就会开始递归, 然后触发 VisitMethodCall, VisitMember, VisitConstant 等等...

我们通过继承 ExpressionVisitor 然后 override 它的各种方法 (大部分是 protect internal) 来拦截整个递归过程.

拦截后可以通过 StringBuilder 拼接 SQL 语句.

大概长这样

这样

这样

总结

反射, 动态创建表达式树, 解析表达式树, 它们本身代码都不好维护, 但是创造出来的东西绝对会让整个项目的代码易于维护许多.

鼓励大家适当的运用在项目中.

ASP.NET Core C# 反射 & 表达式树 (第四篇)的更多相关文章

  1. ASP.NET Core中使用表达式树创建URL

    当我们在ASP.NET Core中生成一个action的url会这样写: var url=_urlHelper.Action("Index", "Home"); ...

  2. 使用Asp.Net Core MVC 开发项目实践[第四篇:基于EF Core的扩展2]

    上篇我们说到了基于EFCore的基础扩展,这篇我们讲解下基于实体结合拉姆达表达式的自定义更新以及删除数据. 先说下原理:其实通过实体以及拉姆达表达式生成SQL语句去执行 第一种更新扩展: 自定义更新字 ...

  3. ASP.NET Core Web开发学习笔记-1介绍篇

    ASP.NET Core Web开发学习笔记-1介绍篇 给大家说声报歉,从2012年个人情感破裂的那一天,本人的51CTO,CnBlogs,Csdn,QQ,Weboo就再也没有更新过.踏实的生活(曾辞 ...

  4. 从零开始实现ASP.NET Core MVC的插件式开发(四) - 插件安装

    标题:从零开始实现ASP.NET Core MVC的插件式开发(四) - 插件安装 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11260750. ...

  5. C# 反射 表达式树 模糊搜索

    反射实体T,非datetime字段反射获取表达式树   public static Expression<Func<T, bool>> GetSearchExpression& ...

  6. 【无私分享:ASP.NET CORE 项目实战(第十四章)】图形验证码的实现

    目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 很长时间没有来更新博客了,一是,最近有些忙,二是,Core也是一直在摸索中,其实已经完成了一个框架了,并且正在准备在生产环境中 ...

  7. ASP.NET Core 中的依赖注入 [共7篇]

    一.控制反转(IoC) ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了 ...

  8. ASP.NET Core 快速入门【第二弹-实战篇】

    上篇讲了asp.net core在linux上的环境部署.今天我们将做几个小玩意实战一下.用到的技术和工具有mysql.websocket.AngleSharp(爬虫html解析).nginx多站点部 ...

  9. 使用 ASP.NET Core MVC 创建 Web API(四)

    使用 ASP.NET Core MVC 创建 Web API 使用 ASP.NET Core MVC 创建 Web API(一) 使用 ASP.NET Core MVC 创建 Web API(二) 使 ...

  10. 使用Asp.Net Core MVC 开发项目实践[第五篇:缓存的使用]

    项目中我们常常会碰到一些数据,需要高频率用到但是又不会频繁变动的这类,我们就可以使用缓存把这些数据缓存起来(比如说本项目的导航数据,帖子频道数据). 我们项目中常用到有Asp.Net Core 本身提 ...

随机推荐

  1. Django REST framework的10个常见组件

    Django REST framework的10个常见组件: 权限组件 认证组件 访问频率限制组件 序列化组件 路由组件 视图组件 分页组件 解析器组件 渲染组件 版本组件

  2. odoo 为form表单视图添加chatter功能

    实践环境 Odoo 14.0-20221212 (Community Edition) 需求描述 如图,给表单新增一个类似聊天的窗口,当记录一些表单活动(本例为自动记录当前记录状态变化) 需求实现 模 ...

  3. 关键点检测(1)——标注关键点检测数据(labelme和CVAT)

    关键点检测,作为计算机视觉领域的重要分支,广泛应用于人体姿态估计.面部表情识别.手部动作分析等多个场景.其核心在于从图像中准确检测并定位特定的关键点位置.然而,高效的模型训练离不开大量高质量的标注数据 ...

  4. 计算机二级考试 C语言篇

    本篇仅适用于计算机二级考试C语言篇 首先介绍一下二级考试时间问题(以本人考试2022年为例): 一. 2022年全国计算机二级考试时间   2022年全国计算机考试举办4次,(3月.5月.9月.12月 ...

  5. DuiLib的编译

    Duilib编译需要注意两点: 加入预处理器:WIN32;_DEBUG;_WINDOWS;UILIB_STATIC; 到这一步还是报错,报错的是DuiString  +=  这一行报错,还有Util这 ...

  6. 搭建lnmp环境-mysql(第五步)

    版本mysql 5.7 先删除系统自带的db 新建文件夹/data/download 进入后下载 wget http://repo.mysql.com/mysql57-community-releas ...

  7. 2023/4/19 SCRUM个人博客

    1.我昨天的任务 初步了解了pandas库,对series和dataframe有了初步的学习使用 2.遇到了什么困难 对PYQT5的概念没有定义,准备进行学习 3.我今天的任务 学习了PYQT5的部分 ...

  8. Jmeter二次开发函数 - 将指定时间转换为时间戳

    1.达到效果:在jmeter的函数助手增加一个"timeStamp"函数,调用"timeStamp"函数可以将用户传入的时间转换为时间戳. 2.eclipse项 ...

  9. 【Java】JNDI实现

    前提情要: 培训的时候都没讲过,也是书上看到过这么个东西,进公司干外包的第二个项目就用了这个鬼东西 自学也不是没尝试过实现,结果各种失败,还找不到问题所在,索性不写了 JNDI实现参考: 目前参考这篇 ...

  10. 论文写作:写回复意见时的套话 (reviews and comments)

    Typos, Grammar, and Citation Errors: We acknowledge the need for a thorough proofreading to rectify ...