• 解析Expression<Func<T, object>>表达式


    前言

      时光荏苒,2020年不觉中已成过去。2021刚刚开头,新的开始本应意气风发、本应有会当凌绝顶豪情壮志,再不济也该“鸿图霸业谈笑间”,且不管一入江湖是不是岁月摧的洒脱。很不幸,有些事情就是会突入其来,搞得你触不及防,什么心情都没有。但是我居然还是写下了这篇博客。。。。。。嗯,总算是有地方表达以我糟糕心情了。

      本来是想解决一下合并两个Expression<Func<T, object>>类型的表达式的问题,比如:

      Expression<Func<T, object>> exp1 = t => t.updateTime; Expression<Func<T, object>> exp2 = t => new {t.age, t.name};

      合并为一个表达式:Expression<Func<T, object>> exp1 = t => new {t.age, t.name, t.updateTime};

      之前尝试过一些办法(比如下图方法1和方法2,但是都失败了)也请教过一些大佬,都没有解决这个问题。于是我只能绕过这个问题用其他方法去实现了业务需求(在这里抛出这个问题,也希望能有人帮我解惑)

      

    退而求其次

      我通过解析出来表达式中指定的属性也能满足我的需求,下面是我的实现方式:

     1         private static List<MemberInfo> SelectMembers(Expression properties)
     2         {
     3             if( properties.NodeType == ExpressionType.Convert)
     4             {
     5                 List<MemberInfo> newArrMembers = new List<MemberInfo>
     6                 {
     7                     ((MemberExpression)((UnaryExpression)properties).Operand).Member
     8                 };
     9                 return newArrMembers;
    10             }
    11             else
    12             {
    13                 var newExp = (NewExpression)properties;
    14                 if (newExp != null)
    15                 {
    16                     return newExp.Members.ToList();
    17                 }
    18                 else
    19                 {
    20                     var newArr = (NewArrayExpression)properties;
    21                     if (newArr != null)
    22                     {
    23                         List<MemberInfo> newArrMembers = new List<MemberInfo>();
    24                         foreach (var newArrExp in newArr.Expressions)
    25                             newArrMembers.AddRange(SelectMembers(newArrExp));
    26                         return newArrMembers.Distinct().ToList();
    27                     }
    28                     return null;
    29                 }
    30             }
    31         }

    如何使用

     1         public override Task<bool> UpdateAsync(T model, Expression<Func<T, object>> properties)
     2         {
     3             var mem = properties.SelectMembers();
     4             if (mem != null)
     5             {
     6                 var sc = mem.Select(t => t.Name).ToArray();
     7                 if (!sc.Contains("Updatedtime")) throw new Exception("表达必须指定updatedtime字段");
     8                 if (sc.Contains("Createdtime")) throw new Exception("不允许更新的字段");
     9             }
    10             model.UpdatedTime = DateTime.Now;
    11             return base.UpdateAsync(model, properties);
    12         }

    下面附上一些实用的扩展

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Dynamic;
      4 using System.Linq;
      5 using System.Linq.Expressions;
      6 using System.Reflection;
      7 
      8 namespace Syspetro.Core.Extensions
      9 {
     10     /// <summary>
     11     /// 合并表达式 And Or  Not扩展
     12     /// </summary>
     13     public static class ExpressionHelper
     14     {
     15         /// <summary>
     16         /// 合并表达式 expr1 AND expr2
     17         /// </summary>
     18         /// <typeparam name="T"></typeparam>
     19         /// <param name="expr1"></param>
     20         /// <param name="expr2"></param>
     21         /// <returns></returns>
     22         public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
     23         {
     24             if (expr1 == null)
     25                 return expr2;
     26             else if (expr2 == null)
     27                 return expr1;
     28             ParameterExpression newParameter = Expression.Parameter(typeof(T), "c");
     29             MyExpressionVisitor visitor = new MyExpressionVisitor(newParameter);
     30             var left = visitor.Visit(expr1.Body);
     31             var right = visitor.Visit(expr2.Body);
     32 
     33             return Expression.Lambda<Func<T, bool>>(Expression.And(left, right), newParameter);
     34         }
     35         /// <summary>
     36         /// 合并表达式 expr1 or expr2
     37         /// </summary>
     38         /// <typeparam name="T"></typeparam>
     39         /// <param name="expr1"></param>
     40         /// <param name="expr2"></param>
     41         /// <returns></returns>
     42         public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
     43         {
     44             if (expr1 == null)
     45                 return expr2;
     46             else if (expr2 == null)
     47                 return expr1;
     48             ParameterExpression newParameter = Expression.Parameter(typeof(T), "c");
     49             MyExpressionVisitor visitor = new MyExpressionVisitor(newParameter);
     50 
     51             var left = visitor.Visit(expr1.Body);
     52             var right = visitor.Visit(expr2.Body);
     53             var body = Expression.Or(left, right);
     54             return Expression.Lambda<Func<T, bool>>(body, newParameter);
     55         }
     56         /// <summary>
     57         /// 取反表达式
     58         /// </summary>
     59         /// <typeparam name="T"></typeparam>
     60         /// <param name="expr"></param>
     61         /// <returns></returns>
     62         public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expr)
     63         {
     64             if (expr == null) return null;
     65             var candidateExpr = expr.Parameters[0];
     66             var body = Expression.Not(expr.Body);
     67 
     68             return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
     69         }
     70         /// <summary>
     71         /// 获取表达式属性列表
     72         /// </summary>
     73         /// <typeparam name="T"></typeparam>
     74         /// <param name="expr"></param>
     75         /// <returns></returns>
     76         public static List<MemberInfo> SelectMembers<T>(this Expression<Func<T, object>> expr)
     77         {
     78             return SelectMembers(expr.Body);
     79         }
     80         private static List<MemberInfo> SelectMembers(Expression properties)
     81         {
     82             if( properties.NodeType == ExpressionType.Convert)
     83             {
     84                 List<MemberInfo> newArrMembers = new List<MemberInfo>
     85                 {
     86                     ((MemberExpression)((UnaryExpression)properties).Operand).Member
     87                 };
     88                 return newArrMembers;
     89             }
     90             else
     91             {
     92                 var newExp = (NewExpression)properties;
     93                 if (newExp != null)
     94                 {
     95                     return newExp.Members.ToList();
     96                 }
     97                 else
     98                 {
     99                     var newArr = (NewArrayExpression)properties;
    100                     if (newArr != null)
    101                     {
    102                         List<MemberInfo> newArrMembers = new List<MemberInfo>();
    103                         foreach (var newArrExp in newArr.Expressions)
    104                             newArrMembers.AddRange(SelectMembers(newArrExp));
    105                         return newArrMembers.Distinct().ToList();
    106                     }
    107                     return null;
    108                 }
    109             }
    110         }
    111     }
    112 }

    总结

      纵然此时你的内心是千疮百孔,万般无奈,那又怎样,你还想继续生活吗?那就只能继续前向,继续拼搏,努力让自己更加强大。所以该做的事情还是要做,加油。

    作者:听枫xl
    本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    解决Data truncation: Truncated incorrect DOUBLE value: 'xxxxxxx';
    免费LOGO在线生成+免费图床 (亲测可用)
    解决问题:bat脚本手动执行没问题,自动执行不成功
    flask上线部署————“WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.”
    钉钉机器人自动推送测试报告
    Python 自动化测试报告通过钉钉机器人推送通知
    转载:如何将新建的项目完整的提交到gitlab上?
    GIT推送时,空文件夹无法添加
    ddt+excel接口自动化测试-HtmlTestRunner报告中用例名称显示excel中自定义的名称
    Exp9 Web安全基础 20154301仉鑫烨
  • 原文地址:https://www.cnblogs.com/xl-tf/p/14226643.html
Copyright © 2020-2023  润新知