• ASP.NET Core C# 反射 & 表达式树 (第四篇)


    前言

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

    我之所以会用到是因为最近开始大量使用 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 语句.

    大概长这样

    这样

    这样

    总结

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

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

  • 相关阅读:
    SciTE 快捷键
    MySQL数据库性能优化
    常用的正则表达式全面总结
    PHP中的Memcache的应用
    经典数学题:态度决定一切
    PHP Socket基础
    由浅入深探究mysql索引结构原理、性能分析与优化
    深入理解HTTP协议
    PHP会话控制之Session介绍原理
    PHP会话控制之Cookie使用例子
  • 原文地址:https://www.cnblogs.com/keatkeat/p/15554245.html
Copyright © 2020-2023  润新知