<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Csharp中表達式樹

      Csharper中的表達式樹

      這節課來了解一下表示式樹是什么?

      在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用于創建動態查詢和解析表達式。

      一、認識表達式樹

      為什么要這樣說?它和委托有什么區別?

      創建一個簡單的表達式樹和委托

        public class ExpressionDemo
        {
      
            void Show()
            {
                Func<int, bool> fun1 = x => x > 10;
                Expression<Func<int, bool>> expression1 = x => x > 10;
            }
        }
      

      然后f12轉到定義

      public sealed class Expression<TDelegate> : LambdaExpression
      

      嘗試用大括號定義一個表達式樹

      img

      debug運行后,用vs查看一下定義的表達式樹對象.
      img

      發現表達式樹一些特點:

      1. 可以通過lambda表達式來聲明
      2. 是一個泛型類的接口,類型參數是一個委托
      3. Expression聲明中,不能包含大括號.
      4. 通過VS展開查看,包含body(lamubda的主體部分),描述了參數的名稱和類型,描述了返回值的名稱和類型; 展開body, body包含 左邊是什么,右邊是什么,式子的操作類型是什么.

      結論:

      表達式樹,是一個計算式的描述,按照常規的計算邏輯,通過類的屬性來進行描述多個節點之間的關系; 形似于一個樹形結構----二叉樹; 二叉樹不斷地去分解,可以得到這個式子中的任何一個獨立的元素;----是一個二叉樹,是一個數據結構; 如果需要可以把這個結構不斷的拆解;得到中間的最小元素;在需要的時候,也可以通過每個元素,組裝起來;

      委托是一個類,而表達式樹是一個二叉樹的數據結構。

      為了更加深入的了解表達式樹,這里也使用ilspy進行反編譯,以便于更加了解表達式樹的本質.

      這里使用一個比較復雜的表達式樹的語句來方便我們去理解

      Expression<Func<int ,int ,int>> expression2= (x, y) => x *y+2+3;
      

      img

      優化一下這段代碼

      //定義2個變量
      ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "x");
      ParameterExpression parameterExpression2 = Expression.Parameter(typeof(int), "y");
      //定義常量
      var contact1 = Expression.Constant(2, typeof(int));
      var contact2= Expression.Constant(3, typeof(int));
      //定義表達式 x*y
      var MultiplyXy= Expression.Multiply(parameterExpression, parameterExpression2);
      //定義表達式 x*y的結果+2
      var add1 = Expression.Add(MultiplyXy, contact1);
      
      //定義表達式 x*y+2的結果+3
      var add2 = Expression.Add(add1, contact2);
      //定義最終的lambda表達式
      Expression<Func<int, int, int>> expression2 = Expression.Lambda<Func<int, int, int>>(add2, new ParameterExpression[2]
      {
          parameterExpression,
          parameterExpression2
      });
      

      如圖所示的解析:

      img

      已經將相應的代碼粘貼到上方,就是類似二叉樹結構的因式分解,轉換成為最小的子問題,最后解決一個需要解決的大問題。

      二、動態拼裝Expression

      我們自己去拼裝一個表達式樹去理解表達式樹的秘密.

      首先創建一個People類

      public class People
      {
          public int Age { get; set; }
          public string Name { get; set; }
          public int Id;
      }
      

      下面來拼接一個比較復雜的表達式

      Expression<Func<People, bool>> predicate = c => c.Id == 10 && c.Name.ToString().Equals("張三");
      

      對應的表達式樹的代碼

        //定義一個People類型的參數
        ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "c");
        //獲取People的Id屬性
        PropertyInfo? propertyId = typeof(People).GetProperty("Id");
        //定義10這個常量
        ConstantExpression constantExpression = Expression.Constant(10, typeof(int));                
        //定義c.Id>10這個表達式    
        BinaryExpression left =Expression.GreaterThan(Expression.Property(parameterExpression, propertyId), constantExpression);
        //獲取People的Name屬性
        PropertyInfo? propertyName = typeof(People).GetProperty("Name");
        //c.Name
        MemberExpression memName = Expression.Property(parameterExpression, propertyName);
        //to string方法
        MethodInfo? methodtostring=typeof(string).GetMethod("ToString",new Type[0]);
        //調用tostring方法
        MethodCallExpression instance =Expression.Call(memName, methodtostring,Array.Empty<Expression>());
        //獲取equals方法
        MethodInfo? methodEquals = typeof(string).GetMethod("Equals", new Type[] { typeof(string) });
        //定義c.Name.ToString().Equals("張三")這個表達式
        MethodCallExpression right = Expression.Call(instance, methodEquals, Expression.Constant("張三", typeof(string)));
        //定義c.Age<25這個表達式
        PropertyInfo? propertyAge = typeof(People).GetProperty("Age");
        ConstantExpression constantExpression2 = Expression.Constant(25, typeof(int));
        BinaryExpression right2 = Expression.LessThan(Expression.Property(parameterExpression, propertyAge), constantExpression2);
        //定義c.Id>10 && c.Name.ToString().Equals("張三") && c.Age<25這個表達式
        BinaryExpression and1 = Expression.AndAlso(left, right);
        BinaryExpression and2 = Expression.AndAlso(and1, right2);
        //定義最終的lambda表達式
        Expression<Func<People, bool>> expression = Expression.Lambda<Func<People, bool>>(and2, new ParameterExpression[1]
        {
            parameterExpression
        });
        //編譯表達式
        Func<People, bool> func = expression.Compile();
        //調用表達式
        People people = new People()
        {
            Id = 11,
            Name = "張三",
            Age = 20
        };
        Console.WriteLine(func(people));
      

      這樣就拼接出來了需要的表達式樹.

      三、表達式樹的應用價值

      為什么要拼裝這個表達式目錄樹呢?

      現在主流的是Linq:
      Linq to Sql -----把相同的邏輯封裝,把不同的邏輯通過表達式目錄樹來傳遞;
      傳遞表達式目錄樹:對應的是查詢條件;在傳遞之前就應該把查詢的條件拼裝好;

      例子

       Expression<Func<People, bool>> expression2 = p => p.Id == 10 && p.Name.Equals("陽光下的微笑");
      

      拼接后的結果

      //按關鍵字是否存在來拼裝;
      Expression<Func<People, bool>> exp = p=> true;
      Console.WriteLine("用戶輸入個名稱,為空就跳過");
      string name = Console.ReadLine();
      if (!string.IsNullOrWhiteSpace(name))
      {
          //exp = p => p.Name.Contains(name);
          exp= exp.And(c=>c.Name.Contains(name));
      }
      Console.WriteLine("用戶輸入個最小年紀,為空就跳過");
      string age = Console.ReadLine();
      if (!string.IsNullOrWhiteSpace(age) && int.TryParse(age, out int iAge))
      {
         //  exp = p => p.Age > iAge;
          exp = exp.And(p => p.Age > iAge);
      }
      
      

      例子2

      //Expression<Func<People, bool>> newExpress = x => x.Age > 5 && x.Id > 5
      

      現在使用表達式樹進行鏈接

       Expression<Func<People, bool>> lambda1 = x => x.Age > 5;
       Expression<Func<People, bool>> lambda2 = x => x.Id > 5;
      
       //Expression<Func<People, bool>> newExpress = x => x.Age > 5 && x.Id > 5;
      
       Expression<Func<People, bool>> lambda3 = lambda1.And(lambda2); //且   兩個都滿足,通過&&鏈接
      
       Expression<Func<People, bool>> lambda4 = lambda1.Or(lambda2);//或   兩個只要有一個就可以  通過或者來鏈接  || 
       Expression<Func<People, bool>> lambda5 = lambda1.Not();//非
      

      這里實現了常見的且、或、非邏輯運算符的表達式

       public static class ExpressionExtend
       {
           /// <summary>
           /// 合并表達式 expr1 AND expr2
           /// </summary>
           /// <typeparam name="T"></typeparam>
           /// <param name="expr1"></param>
           /// <param name="expr2"></param>
           /// <returns></returns>
           public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
           {
               //return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters);
      
               ParameterExpression newParameter = Expression.Parameter(typeof(T), "c");
               NewExpressionVisitor visitor = new NewExpressionVisitor(newParameter);
               var left = visitor.Replace(expr1.Body);
               var right = visitor.Replace(expr2.Body); //為了能夠生成一個新的表達式目錄樹
      
               var body = Expression.And(left, right);
                return Expression.Lambda<Func<T, bool>>(body, newParameter);
      
           }
           /// <summary>
           /// 合并表達式 expr1 or expr2
           /// </summary>
           /// <typeparam name="T"></typeparam>
           /// <param name="expr1"></param>
           /// <param name="expr2"></param>
           /// <returns></returns>
           public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
           {
      
               ParameterExpression newParameter = Expression.Parameter(typeof(T), "c");
               NewExpressionVisitor visitor = new NewExpressionVisitor(newParameter);
      
               var left = visitor.Replace(expr1.Body);
               var right = visitor.Replace(expr2.Body);
               var body = Expression.Or(left, right);
               return Expression.Lambda<Func<T, bool>>(body, newParameter);
           }
           public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expr)
           {
               var candidateExpr = expr.Parameters[0];
               var body = Expression.Not(expr.Body);
      
               return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
           }
       }
      
       internal class NewExpressionVisitor : ExpressionVisitor
      {
          public ParameterExpression _NewParameter { get; private set; }
          public NewExpressionVisitor(ParameterExpression param)
          {
              this._NewParameter = param;
          }
          public Expression Replace(Expression exp)
          {
              return this.Visit(exp);
          }
          protected override Expression VisitParameter(ParameterExpression node)
          {
              return this._NewParameter;
          }
      }
      

      現在有一個新的需求,需要把People拷貝到NewPeople這個新的類,來看下效率怎么樣?

      People和PeopleCopy類

       public class People
       {
           public int Age { get; set; }
           public string Name { get; set; }
           public int Id;
       }
       /// <summary>
       /// 實體類Target
       /// PeopleDTO
       /// </summary>
       public class PeopleCopy
       {
      
           public int Age { get; set; }
           public string Name { get; set; }
           public int Id;
       }
      

      直接賦值的方式

       PeopleCopy peopleCopy1 = new PeopleCopy()
       {
           Id = people.Id,
           Name = people.Name,
           Age = people.Age
       };
      

      反射賦值的方式

       public class ReflectionMapper
       {
           /// <summary>
           /// 反射
           /// </summary>
           /// <typeparam name="TIn"></typeparam>
           /// <typeparam name="TOut"></typeparam>
           /// <param name="tIn"></param>
           /// <returns></returns>
           public static TOut Trans<TIn, TOut>(TIn tIn)
           {
               TOut tOut = Activator.CreateInstance<TOut>();
               foreach (var itemOut in tOut.GetType().GetProperties())
               {
                   var propName = tIn.GetType().GetProperty(itemOut.Name);
                   itemOut.SetValue(tOut, propName.GetValue(tIn)); 
               }
      
               foreach (var itemOut in tOut.GetType().GetFields())
               {
                   var fieldName = tIn.GetType().GetField(itemOut.Name);
                   itemOut.SetValue(tOut, fieldName.GetValue(tIn)); 
               }
               return tOut;
           }
       }
       PeopleCopy peopleCopy2= ReflectionMapper.Trans<People, PeopleCopy>(people);
      

      json序列化的方式

      public class SerializeMapper
      {
          /// <summary>
          /// 序列化反序列化方式
          /// </summary>
          /// <typeparam name="TIn"></typeparam>
          /// <typeparam name="TOut"></typeparam>
          public static TOut Trans<TIn, TOut>(TIn tIn)
          { 
              string strTin = JsonConvert.SerializeObject(tIn); 
              return JsonConvert.DeserializeObject<TOut>(strTin);
          }
      }
       PeopleCopy peopleCopy3 = SerializeMapper.Trans<People, PeopleCopy>(people);
      

      表達式目錄樹的方式

      
      public class ExpressionMapper
      {
          /// <summary>
          /// 字典緩存--hash分布
          /// </summary>
          private static Dictionary<string, object> _Dic = new Dictionary<string, object>();
      
          /// <summary>
          /// 字典緩存表達式樹
          /// </summary>
          /// <typeparam name="TIn"></typeparam>
          /// <typeparam name="TOut"></typeparam>
          /// <param name="tIn"></param>
          /// <returns></returns>
          public static TOut Trans<TIn, TOut>(TIn tIn)
          {
              string key = string.Format("funckey_{0}_{1}", typeof(TIn).FullName, typeof(TOut).FullName);
              if (!_Dic.ContainsKey(key))
              {
                  #region 這里是拼裝---賦屬性值的代碼 
                  ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
                  //MemberBinding: 就是一個表達式目錄樹
                  List<MemberBinding> memberBindingList = new List<MemberBinding>();
                  foreach (var item in typeof(TOut).GetProperties())   //這里是處理屬性的
                  {
                      MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
      
                      MemberBinding memberBinding = Expression.Bind(item, property);
      
                      memberBindingList.Add(memberBinding);
                  }
                  foreach (var item in typeof(TOut).GetFields()) //處理字段的
                  {
                      MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
                      MemberBinding memberBinding = Expression.Bind(item, property);
                      memberBindingList.Add(memberBinding);
                  }
                  MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());  //組裝了一個轉換的過程;
      
                  Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
                  {
                      parameterExpression
                  });
      
                  #endregion
      
      
                  Func<TIn, TOut> func = lambda.Compile();//拼裝是一次性的
                  _Dic[key] = func;
              }
              return ((Func<TIn, TOut>)_Dic[key]).Invoke(tIn);
          }
      }
      PeopleCopy peopleCopy4 = ExpressionMapper.Trans<People, PeopleCopy>(people);
      

      表達式+反射+泛型類的方式

          public class ExpressionGenericMapper<TIn, TOut>//Mapper`2
          {
              private static Func<TIn, TOut> _FUNC = null;
              static ExpressionGenericMapper()
              {
                  ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
                  List<MemberBinding> memberBindingList = new List<MemberBinding>();
                  foreach (var item in typeof(TOut).GetProperties())
                  {
                      MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
                      MemberBinding memberBinding = Expression.Bind(item, property);
                      memberBindingList.Add(memberBinding);
                  }
                  foreach (var item in typeof(TOut).GetFields())
                  {
                      MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
                      MemberBinding memberBinding = Expression.Bind(item, property);
                      memberBindingList.Add(memberBinding);
                  }
                  MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
                  Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
                  {
                          parameterExpression
                  });
                  _FUNC = lambda.Compile();//拼裝是一次性的
              }
              public static TOut Trans(TIn t)
              {
                  return _FUNC(t);
              }
          }
      }
      PeopleCopy peopleCopy5 = ExpressionGenericMapper<People, PeopleCopy>.Trans(people);
      

      最后運行一百萬次,來看一下效率。

      {
          People people = new People()
          {
              Id = 11,
              Name = "Richard",
              Age = 31
          };
          long common = 0;
          long generic = 0;
          long cache = 0;
          long reflection = 0;
          long serialize = 0;
          {
              Stopwatch watch = new Stopwatch();
              watch.Start();
              for (int i = 0; i < 1_000_000; i++)
              {
                  PeopleCopy peopleCopy = new PeopleCopy()
                  {
                      Id = people.Id,
                      Name = people.Name,
                      Age = people.Age
                  };
              }
              watch.Stop();
              common = watch.ElapsedMilliseconds;
          }
          {
              Stopwatch watch = new Stopwatch();
              watch.Start();
              for (int i = 0; i < 1_000_000; i++)
              {
                  PeopleCopy peopleCopy = ReflectionMapper.Trans<People, PeopleCopy>(people);
              }
              watch.Stop();
              reflection = watch.ElapsedMilliseconds;
          }
          {
              Stopwatch watch = new Stopwatch();
              watch.Start();
              for (int i = 0; i < 1_000_000; i++)
              {
                  PeopleCopy peopleCopy = SerializeMapper.Trans<People, PeopleCopy>(people);
              }
              watch.Stop();
              serialize = watch.ElapsedMilliseconds;
          }
          {
      
              Stopwatch watch = new Stopwatch();
              watch.Start();
              for (int i = 0; i < 1_000_000; i++)
              {
                  PeopleCopy peopleCopy = ExpressionMapper.Trans<People, PeopleCopy>(people);
              }
              watch.Stop();
              cache = watch.ElapsedMilliseconds;
          }
          {
              Stopwatch watch = new Stopwatch();
              watch.Start();
              for (int i = 0; i < 1_000_000; i++)
              {
                  PeopleCopy peopleCopy = ExpressionGenericMapper<People, PeopleCopy>.Trans(people);
              }
              watch.Stop();
              generic = watch.ElapsedMilliseconds;
          }
      
          Console.WriteLine($"common = {common} ms");        //性能最高,但是不能通用;
          Console.WriteLine($"reflection = {reflection} ms");
          Console.WriteLine($"serialize = {serialize} ms");
          Console.WriteLine($"cache = {cache} ms");
          Console.WriteLine($"generic = {generic} ms"); //性能好,而且擴展性也好===又要馬兒跑,又要馬兒不吃草。。。
      }
      

      看運行后的結果
      img

      核心:動態生成硬編碼;----代碼運行的時候生成了一段新的邏輯;

      四、表達式樹和sql

      為什么要使用表達式目錄樹來拼裝解析呢?
      可以提供重用性

      如果封裝好一個方法,接受一個表達式樹,在解析的時候,其實就是不斷的訪問,訪問的時候,會按照固定的規則,避免出錯;

      任何的一個表達式樹都可以用一個通用的方法解析并且支持泛型,更加容易去封裝;

      例子:

      需要的擴展類

       public class OperationsVisitor : ExpressionVisitor
       {
           public Expression Modify(Expression expression)
           {
               Console.WriteLine(expression.ToString()) ;
      
               //ExpressionVisitor:
               //1.Visit方法--訪問表達式目錄樹的入口---分辨是什么類型的表達式目錄
               //2.調度到更加專業的方法中進一步訪問,訪問一遍之后,生成一個新的表達式目錄   ---有點像遞歸,不全是遞歸;
               //3.因為表達式目錄樹是個二叉樹,ExpressionVisitor一直往下訪問,一直到葉節點;那就訪問了所有的節點
               //4.在訪問的任何一個環節,都可以拿到對應當前環節的內容(參數名稱、參數值。。),就可以進一步擴展
               return this.Visit(expression);
           }
      
           /// <summary>
           /// 覆寫父類方法
           /// </summary>
           /// <param name="b"></param>
           /// <returns></returns>
           protected override Expression VisitBinary(BinaryExpression b)
           {
              
               if (b.NodeType == ExpressionType.Add)
               {
                   Expression left = this.Visit(b.Left);
                   Expression right = this.Visit(b.Right);
                   return Expression.Subtract(left, right);
               }
               else if (b.NodeType==ExpressionType.Multiply) //如果是相乘
               {
                   Expression left = this.Visit(b.Left);
                   Expression right = this.Visit(b.Right);
                   return Expression.Divide(left, right); //相除
               } 
               return base.VisitBinary(b);
           }
      
           /// <summary>
           /// 覆寫父類方法
           /// </summary>
           /// <param name="node"></param>
           /// <returns></returns>
           protected override Expression VisitConstant(ConstantExpression node)
           {
               return base.VisitConstant(node);
           }
      

      對應的表達式解析

       Expression<Func<int, int, int>> exp = (m, n) => m * n + 2;
       OperationsVisitor visitor = new OperationsVisitor();
       //visitor.Visit(exp);
       Expression expNew = visitor.Modify(exp);
      

      同時表達式樹中已經通過使用觀察者模式封裝好了Visit方法.

      1. Visit方法--訪問表達式樹的入口---分辨是什么類型的表達式目錄
      2. 調度到更加專業的方法中進一步訪問,訪問一邊以后,生成一個新的表達式目錄. --- 有點像遞歸,不全是遞歸
      3. 因為表達式目錄樹是一個二叉樹,ExpreesionVistor一直往下訪問,一直到葉子節點;通過二叉樹的遍歷就訪問了所有的節點.
      4. 在訪問的任何一個環節,都可以拿到對應當前環節的內容(參數名稱、參數值...)就可以進一步擴展.

      現在開始將表達式樹跟sql語句進行連接

      例子:
      擴展類

       public class ConditionBuilderVisitor : ExpressionVisitor
       {
           private Stack<string> _StringStack = new Stack<string>();
      
           public string Condition()
           {
               string condition = string.Concat(this._StringStack.ToArray());
               this._StringStack.Clear();
               return condition;
           }
      
           /// <summary>
           /// 如果是二元表達式
           /// </summary>
           /// <param name="node"></param>
           /// <returns></returns>
           protected override Expression VisitBinary(BinaryExpression node)
           {
               if (node == null) throw new ArgumentNullException("BinaryExpression");
      
               this._StringStack.Push(")");
               base.Visit(node.Right);//解析右邊
               this._StringStack.Push(" " + node.NodeType.ToSqlOperator() + " ");
               base.Visit(node.Left);//解析左邊
               this._StringStack.Push("(");
      
               return node;
           }
      
           /// <summary>
           /// 解析屬性
           /// </summary>
           /// <param name="node"></param>
           /// <returns></returns>
           protected override Expression VisitMember(MemberExpression node)
           {
               if (node == null) throw new ArgumentNullException("MemberExpression");
               //this._StringStack.Push(" [" + node.Member.Name + "] ");
               ////return node; 
               if (node.Expression is ConstantExpression)
               {
                   var value1 = this.InvokeValue(node);
                   var value2 = this.ReflectionValue(node);
                   //this.ConditionStack.Push($"'{value1}'");
                   this._StringStack.Push("'" + value2 + "'");
               }
               else
               {
                   this._StringStack.Push(" [" + node.Member.Name + "] ");
               }
               return node;
           }
      
      
           private object InvokeValue(MemberExpression member)
           {
               var objExp = Expression.Convert(member, typeof(object));//struct需要
               return Expression.Lambda<Func<object>>(objExp).Compile().Invoke();
           }
      
           private object ReflectionValue(MemberExpression member)
           {
               var obj = (member.Expression as ConstantExpression).Value;
               return (member.Member as FieldInfo).GetValue(obj);
           }
      
           /// <summary>
           /// 常量表達式
           /// </summary>
           /// <param name="node"></param>
           /// <returns></returns>
           protected override Expression VisitConstant(ConstantExpression node)
           {
               if (node == null) throw new ArgumentNullException("ConstantExpression");
               this._StringStack.Push(" '" + node.Value + "' ");
               return node;
           }
           /// <summary>
           /// 方法表達式
           /// </summary>
           /// <param name="m"></param>
           /// <returns></returns>
           protected override Expression VisitMethodCall(MethodCallExpression m)
           {
               if (m == null) throw new ArgumentNullException("MethodCallExpression");
      
               string format;
               switch (m.Method.Name)
               {
                   case "StartsWith":
                       format = "({0} LIKE {1}+'%')";
                       break;
      
                   case "Contains":
                       format = "({0} LIKE '%'+{1}+'%')";
                       break;
      
                   case "EndsWith":
                       format = "({0} LIKE '%'+{1})";
                       break;
      
                   default:
                       throw new NotSupportedException(m.NodeType + " is not supported!");
               }
               this.Visit(m.Object);
               this.Visit(m.Arguments[0]);
               string right = this._StringStack.Pop();
               string left = this._StringStack.Pop();
               this._StringStack.Push(String.Format(format, left, right));
      
               return m;
           }
       }
      

      對應的sql語句的解析

      { 
          Expression<Func<People, bool>> lambda = x => x.Age > 5 && x.Id > 5
                                                   && x.Name.StartsWith("1") //  like '1%'
                                                   && x.Name.EndsWith("1") //  like '%1'
                                                   && x.Name.Contains("1");//  like '%1%'
      
          string sql = string.Format("Delete From [{0}] WHERE [Age]>5 AND [ID] >5"
              , typeof(People).Name
              , " [Age]>5 AND [ID] >5");
      
          ConditionBuilderVisitor vistor = new ConditionBuilderVisitor();
          vistor.Visit(lambda);
          Console.WriteLine(vistor.Condition());
      }
      {
          //  ((( [Age] > '5') AND( [Name] =  [name] )) OR( [Id] > '5' )) 
          string name = "AAA";
          Expression<Func<People, bool>> lambda = x => x.Age > 5 && x.Name == name || x.Id > 5;
          ConditionBuilderVisitor vistor = new ConditionBuilderVisitor();
          vistor.Visit(lambda);
          Console.WriteLine(vistor.Condition());
      }
      {
          Expression<Func<People, bool>> lambda = x => x.Age > 5 || (x.Name == "A" && x.Id > 5);
          ConditionBuilderVisitor vistor = new ConditionBuilderVisitor();
          vistor.Visit(lambda);
          Console.WriteLine(vistor.Condition());
      }
      {
          Expression<Func<People, bool>> lambda = x => (x.Age > 5 || x.Name == "A") && x.Id > 5;
          ConditionBuilderVisitor vistor = new ConditionBuilderVisitor();
          vistor.Visit(lambda);
          Console.WriteLine(vistor.Condition());
      }
      

      在我自己的看法,使用表達式樹而不是傳統的方式去解析sql語句的優點

      1. 通過二叉樹的方式表達,更加的有條理性
      2. 使用泛型等技術更方式實現一個通用的sql語句的解析。
      3. 會有類型檢查,出錯后也能使用異常處理。
      posted @ 2024-03-27 16:51  飄雨的河  閱讀(641)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品无码无需播放器| 久久精品国产亚洲AV麻| 忍着娇喘人妻被中出中文字幕| 少妇又爽又刺激视频| 国产精品无码不卡在线播放 | 午夜通通国产精品福利| 在国产线视频A在线视频| 亚洲最大的成人网站| 免费a级毛片18以上观看精品| 亚洲情色av一区二区| 国产95在线 | 亚洲| 天堂av在线一区二区| 亚洲图片自拍偷图区| 鲁丝片一区二区三区免费| 久久精品蜜芽亚洲国产AV| 日韩大片一区二区三区| 最新精品露脸国产在线| 亚洲人成色99999在线观看| 国产视频一区二区| 国产国产久热这里只有精品| 亚洲一本二区偷拍精品| 赣州市| 涩涩爱狼人亚洲一区在线| 52熟女露脸国语对白视频| 亚洲AVAV天堂AV在线网阿V| 欧美18videosex性欧美tube1080 | 久久婷婷大香萑太香蕉AV人| av无码一区二区大桥久未| 中文字幕亚洲制服在线看 | 九九成人免费视频| h动态图男女啪啪27报gif| 69天堂人成无码免费视频| 亚洲中文字幕一区二区| 午夜性爽视频男人的天堂| 东京道一本热中文字幕| 国产亚洲av手机在线观看| 色综合久久精品亚洲国产| 久久亚洲国产精品久久| 日韩欧美猛交xxxxx无码| 亚洲一区精品视频在线| 久久精品国产99久久无毒不卡|