解析Expression >表達式


前言

  時光荏苒,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 }

 

 

總結

  縱然此時你的內心是千瘡百孔,萬般無奈,那又怎樣,你還想繼續生活嗎?那就只能繼續前向,繼續拼搏,努力讓自己更加強大。所以該做的事情還是要做,加油。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM