前言
時光荏苒,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 }
總結
縱然此時你的內心是千瘡百孔,萬般無奈,那又怎樣,你還想繼續生活嗎?那就只能繼續前向,繼續拼搏,努力讓自己更加強大。所以該做的事情還是要做,加油。
