编程语言
首页 > 编程语言> > ASP.NET Core C# 反射 & 表达式树 (第四篇)

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 语句.

大概长这样

这样

这样

 

 

总结

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

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

 

标签:node,Core,ASP,ExpressionVisitor,C#,BiddingPrice,new,public,表达式
来源: https://www.cnblogs.com/keatkeat/p/15554245.html