解析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
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/xl-tf/p/14226643.html