解析Expression<Func<T, object>>表达式
前言
时光荏苒,2020年不觉中已成过去。2021刚刚开头,新的开始本应意气风发、本应有会当凌绝顶豪情壮志,再不济也该“鸿图霸业谈笑间”,且不管一入江湖是不是岁月摧的洒脱。很不幸,有些事情就是会突入其来,搞得你触不及防,什么心情都没有。但是我居然还是写下了这篇博客。。。。。。嗯,总算是有地方表达以我糟糕心情了。
本来是想解决一下合并两个Expression
Expression
合并为一个表达式:Expression
之前尝试过一些办法(比如下图方法1和方法2,但是都失败了)也请教过一些大佬,都没有解决这个问题。于是我只能绕过这个问题用其他方法去实现了业务需求(在这里抛出这个问题,也希望能有人帮我解惑)
退而求其次
我通过解析出来表达式中指定的属性也能满足我的需求,下面是我的实现方式:
1 private static ListSelectMembers(Expression properties) 2 { 3 if( properties.NodeType == ExpressionType.Convert) 4 { 5 List newArrMembers = new List 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 newArrMembers = new List (); 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, Expressionobject>> 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 ///11 /// 合并表达式 And Or Not扩展 12 /// 13 public static class ExpressionHelper 14 { 15 /// 16 /// 合并表达式 expr1 AND expr2 17 /// 18 /// 19 /// 20 /// 21 /// 22 public static Expression bool>> And (this Expression bool>> expr1, Expression 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 bool>>(Expression.And(left, right), newParameter); 34 } 35 /// 36 /// 合并表达式 expr1 or expr2 37 /// 38 /// 39 /// 40 /// 41 /// 42 public static Expression bool>> Or (this Expression bool>> expr1, Expression 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 bool>>(body, newParameter); 55 } 56 /// 57 /// 取反表达式 58 /// 59 /// 60 /// 61 /// 62 public static Expression bool>> Not (this Expression 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 bool>>(body, candidateExpr); 69 } 70 /// 71 /// 获取表达式属性列表 72 /// 73 /// 74 /// 75 /// 76 public static List SelectMembers (this Expression object>> expr) 77 { 78 return SelectMembers(expr.Body); 79 } 80 private static List SelectMembers(Expression properties) 81 { 82 if( properties.NodeType == ExpressionType.Convert) 83 { 84 List newArrMembers = new List 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 newArrMembers = new List (); 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 }
总结
纵然此时你的内心是千疮百孔,万般无奈,那又怎样,你还想继续生活吗?那就只能继续前向,继续拼搏,努力让自己更加强大。所以该做的事情还是要做,加油。