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