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

2021/11/15 9:10:12

本文主要是介绍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 语句.

大概长这样

这样

这样

 

 

总结

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

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

 



这篇关于ASP.NET Core C# 反射 & 表达式树 (第四篇)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程