好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

List<T>列表通用过滤

List<T>列表通用过滤

List<T>列表通用过滤模块设计

需求描述

数据列表如List<Customer> 加载到DataGridView后,如果记录比较多可能需要对其进行二次过滤,即客户端过滤
过滤条件做成可由用户设置的,如下图:

在数据源是DataTable时,使用DataView的RowFilter可以轻松按用户的配置拼接出过滤表达式字符串来,
设置RowFilter就可以实现过滤效果,但是当数据源是List<T>这样由EF,Linq to sql 等框架返回的集合时要实现上面的功能就需要费点力气了。

问题分析:

首先参考上面的截图,用户设置好过滤条件后会形成:" (工号 = 222 And 部门=人力) Or 性别=女" 这样的过滤表达式,可以表示成(Exp1 And Exp2) Or Exp3 这样的形式.针对"工号=222"这样的Exp求值我们会转变成针对Employe实体的EmpId属性是否等于222的判断(Employe.EmpId==222),这个可以通过反射方式来实现,将多个Exp求值的结果通过And或Or连接并运算得出最终结果,True表示这一行(Employe)符合.

不过考虑Exp1 Or Exp2 Or Exp3  这样的条件,如果第一个Exp1是True的话结果必定是True,这个时候还去计算Exp2,Exp3是完全多余的,如果List集合有几万条记录(当然超过几千行的列表对用户来说是没有多少意义的,一般人不会看那么多行,这个时候应该想想过滤条件设置是否合理)那么针对列表的每个实体的每个属性(字段)使用反射的方式计算一遍Exp将是一个比较大的开销,好在And与Or跟算术操作符(+,-,*,/)有所不同,And运算时只要两个操作数中有一个是False就没必要计算另外一个操作数(这里的是Exp)而Or在一个操作数是True时就可以忽略另一个操作数。不过当所的Exp都是false时针对上面"Exp1 Or Exp2 Or Exp3"这样的表达式计算每个Exp是不可避免的

到这里我们可以看到该问题的本质就是表达式求值,而操作符只限And与Or两个二元操作符,最后结果是True或False.

设计实现:


首先我们将用户设置的过滤表达式转变成逆波兰式(后缀表达式),接着传入每个要判断的实体,使用后缀表达式求出该实体是否符合过滤条件,
当然我们也可以将后缀表达式构建成Expression树,接着将该Expression编译成动态方法(委托),使用该委托对每个实体做出判断,下面的代码给出了这两种实现,
经过测试发现两种方法速度区别不大。

自己对逆波兰式求值时需要下面的判定表,如果构建Expression树则Expression.AndAlso或Expression.OrElse会自己判断是否对两个操作数都进行计算(参考下面的代码)

代码:

View Code

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.Linq.Expressions;
  using   System.Reflection;
  namespace   FIStudio.WinUI.Core
{
      public   class   ExpParser
    {
        
          public  ExpParser(List<Elem>  midfixList)
        {
              this .MidfixList =  midfixList;

        }
          public  List<Elem> PostfixList {  get ;  private   set  ; }
          public  List<Elem> MidfixList {  get ;  private   set  ; }
          private  Stack<Elem> CalcStack =  new  Stack<Elem> ();
          private   void   GuardMidfixListExist()
        {
              if  (MidfixList ==  null  || MidfixList.Count <=  0 )  throw   new  Exception( "  中序列表为null或为空!  "  );
        }
          private   void   EnsurePostfixReady()
        {
              if  (PostfixList ==  null  )
            {
                PostfixList  =  DoParse(MidfixList);
                  if  (PostfixList ==  null  || PostfixList.Count <=  0 )  throw   new  Exception( "  后序列表为null或为空!  "  );
            }
        }
          ///   <summary> 
         ///   判断元素是否符合要求
          ///   </summary> 
         ///   <param name="ent"></param> 
         ///   <returns></returns> 
         public   bool  IsSatisfy( object   ent)
        {
            GuardMidfixListExist();
            EnsurePostfixReady();


            CalcStack.Clear();
              foreach  ( var  item  in   PostfixList)
            {
                  if  (item  is   ExpElem)
                {
                    CalcStack.Push(item);
                      continue  ;
                }
                  #region  And 运算
                 if  (item  is   AndElem)
                {
                      var  op1 = CalcStack.Pop()  as   ExpElem;
                      var  op2 = CalcStack.Pop()  as   ExpElem;

                      //  任意一个是false则直接压入false 
                     if  (op1.Result ==  false  || op2.Result ==  false  )
                    {
                        CalcStack.Push(  new  ExpElem() { Result =  false   });
                          continue  ;
                    }

                      if  (!op1.Result.HasValue && ! op2.Result.HasValue)
                    {
                        op1.Compare(ent);
                          if  (op1.Result.Value ==  false  )
                        {
                            CalcStack.Push(  new  ExpElem() { Result =  false   });
                              continue  ;
                        }
                        op2.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op2.Result });
                          continue  ;
                    }
                      if  (!op1.Result.HasValue && op2.Result ==  true  )
                    {
                        op1.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op1.Result });
                          continue  ;
                    }
                      if  (op1.Result ==  true  && ! op2.Result.HasValue)
                    {
                        op2.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op2.Result });
                          continue  ;

                    }
                      if  (op1.Result ==  true  && op2.Result ==  true  )
                    {
                        CalcStack.Push(  new  ExpElem() { Result =  true   });
                          continue  ;
                    }

                }
                  #endregion 
                 #region  Or 运算
                 if  (item  is   OrElem)
                {
                      var  op1 = CalcStack.Pop()  as   ExpElem;
                      var  op2 = CalcStack.Pop()  as   ExpElem;

                      //  任意一个是true则直接压入true 
                     if  (op1.Result ==  true  || op1.Result ==  true  )
                    {
                        CalcStack.Push(  new  ExpElem() { Result =  true   });
                          continue  ;
                    }

                      if  (!op1.Result.HasValue && ! op2.Result.HasValue)
                    {
                        op1.Compare(ent);
                          if  (!op1.Result ==  true  )
                        {
                            CalcStack.Push(  new  ExpElem() { Result =  true   });
                              continue  ;
                        }
                        op2.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op2.Result });
                    }
                      if  (!op1.Result.HasValue && op2.Result ==  false  )
                    {
                        op1.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op1.Result });
                          continue  ;
                    }
                      if  (op1.Result ==  false  && ! op2.Result.HasValue)
                    {
                        op2.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op2.Result });

                          continue  ;
                    }
                      if  (op1.Result ==  false  && op2.Result ==  false  )
                    {
                        CalcStack.Push(  new  ExpElem() { Result =  false   });
                    }

                }
                  #endregion  
            }
              return  (CalcStack.Pop()  as   ExpElem).Result.Value;

        }
          ///   <summary> 
         ///   生成判断函数
          ///   </summary> 
         ///   <returns></returns> 
         public   Expression<Func<T, bool >> GenIsSatisfyFunc<T> ()
        {
            GuardMidfixListExist();
            EnsurePostfixReady();
            Stack < object > stack =  new  Stack< object > ();

            ParameterExpression entExp  = Expression.Parameter( typeof (T),  "  ent  "  );
              foreach  ( var  elem  in   PostfixList)
            {

                  if  (elem  is   ExpElem)
                {
                    stack.Push(elem);
                      continue  ;
                }
                  if  (elem  is   AndElem)
                {
                      var  elem1 =  stack.Pop();
                      var  elem2 =  stack.Pop();

                      var  exp=  Expression.AndAlso(GetCallExpression(elem1,entExp),GetCallExpression(elem2,entExp));
                    
                    stack.Push(exp);
                      continue  ;
                }
                  if (elem  is   OrElem)
                {
                      var  elem1 =  stack.Pop();
                      var  elem2 =  stack.Pop();

                      var  exp=  Expression.OrElse(GetCallExpression(elem1,entExp),GetCallExpression(elem2,entExp));
                    
                    stack.Push(exp);
                      continue  ;
                }
            }
            LambdaExpression lambda = Expression.Lambda<Func<T, bool >>( stack.Pop()  as   Expression,entExp);

              return  lambda  as   Expression<Func<T, bool >> ;

        }
          private  Expression GetCallExpression( object   elem, ParameterExpression entExp)
        {
              if  (elem  is   ExpElem)
            {
                 return  Expression.Call(Expression.Constant(elem),  typeof (ExpElem).GetMethod( "  Compare  "  ), entExp);
            }
              return  elem  as   Expression;
        }
          ///   <summary> 
         ///   中序表达式转后缀表达式
          ///   </summary> 
         ///   <param name="midfix"></param> 
         ///   <returns></returns> 
         private   List<Elem> DoParse(List<Elem>  midfix)
        {
            Stack <Elem> stack =  new  Stack<Elem> ();
              var  list= new  List<Elem> ();
              foreach  ( var  elem  in   midfix)
            {
                  if  (elem  is   ExpElem)
                {
                    list.Add(elem);
                      continue  ;
                }
                  if  (elem  is   LBElem)
                {
                    stack.Push(elem);
                      continue  ;
                }
                  if  (elem  is   RBElem)
                {
                      var  e =  stack.Pop();
                      while  (!(e  is   LBElem))
                    {
                        list.Add(e);
                        e  =  stack.Pop();
                      

                    }
                      continue  ;
                }
                  if ((elem  is  AndElem) || (elem  is   OrElem))
                {
                      if  (stack.Count >  0  )
                    {
                          var  e =  stack.Peek();
                          while  ( !(e  is  LBElem) && elem.Priority <=  e.Priority)
                        {
                            list.Add(stack.Pop());
                              if  (stack.Count <=  0 )  break  ;
                            e  =  stack.Peek();
                        }
                    }
                    stack.Push(elem);
                }

            }
              while  (stack.Count >  0  )
            {
                list.Add(stack.Pop());
            }

              return   list;

        }
    }
      #region  节点定义
     public   class   Elem
    {
          public   virtual   string  Name {  get ;  set  ; }
          public   virtual   int  Priority {  get ;  set  ; }
          public  Object Data {  get ;  set  ; }
    }
      ///   <summary> 
     ///   左括号
      ///   注意stack中只会压入'(','And','Or'
      ///   </summary> 
     public   class   LBElem : Elem
    {
          public   override   string   Name
        {
              get  
            {
                  return   "  (  "  ;
            }
        }
          public   override   int   Priority
        {
              get  
            {
                  return   59  ;
            }
        }
    }
      ///   <summary> 
     ///   右括号
      ///   </summary> 
     public   class   RBElem : Elem
    {
          public   override   string   Name
        {
              get  
            {
                  return   "  )  "  ;
            }
        }
          public   override   int   Priority
        {
              get  
            {
                  return   99  ;
            }
        }

    }

      public   class   AndElem : Elem
    {
          public   override   string   Name
        {
              get  
            {
                  return   "  And  "  ;
            }
        }
          public   override   int   Priority
        {
              get  
            {
                  return   88  ;
            }
        }
    }

      public   class   OrElem : Elem
    {
          public   override   string   Name
        {
              get  
            {
                  return   "  Or  "  ;
            }
        }
          public   override   int   Priority
        {
              get  
            {
                  return   77  ;
            }
        }
    }
      public   class   ExpElem : Elem
    {

          public   override   int   Priority
        {
              get  
            {
                  return   66  ;
            }
        }
          public   bool  Compare( object   ent)
        {
            Console.WriteLine(  "  计算了:  "  +  Name);
              bool ? ret= null  ;
              if  (AssertType ==  Core.CompareType.Equal)
            {
                ret =  string .Compare(GetV(ent),Value, true )== 0  ;
            }
              if  (AssertType ==  Core.CompareType.NotEqual)
            {
                ret  =   string .Compare(GetV(ent), Value,  true ) !=  0  ;
            }
              if  (AssertType ==  Core.CompareType.Greate)
            {
                ret  =  string .Compare(GetV(ent), Value,  true ) >  0  ;
            }
              if  (AssertType ==  Core.CompareType.GreateOrEqual)
            {
                ret  =  string .Compare(GetV(ent), Value,  true ) >=  0  ;
            }
              if  (AssertType ==  Core.CompareType.Less)
            {
                ret  =  string .Compare(GetV(ent), Value,  true ) <  0  ;
            }
              if  (AssertType ==  Core.CompareType.LessOrEqual)
            {
                ret  =  string .Compare(GetV(ent), Value,  true ) <=  0  ;
            }
              if  (AssertType ==  Core.CompareType.Contains)
            {
                ret  =  GetV(ent).Contains(Value);
            }
              if  (AssertType ==  Core.CompareType.NoContains)
            {
                ret  =!  GetV(ent).Contains(Value);
            }
              if  (AssertType ==  Core.CompareType.StartWith)
            {
                ret  =  GetV(ent).StartsWith(Value);
            }
              if  (AssertType ==  Core.CompareType.EndWith)
            {
                ret  =  GetV(ent).EndsWith(Value);
            }
              if  (!ret.HasValue)  throw   new  Exception( "  未知的CompareType!  "  );
            Result  =  ret;
              return   ret.Value;

           
        }
          public   bool ? Result {  get ;  set  ; }
          public  PropertyInfo Property {  get ;  set  ; }
          public  CompareType AssertType {  get ;  set  ; }
          public   string  Value {  get ;  set  ; }

          private   string  GetV( object   ent)
        {
              var  tmp= Property.GetValue(ent,  null  );
              if  (tmp ==  null ) tmp =  string  .Empty;
              return   tmp.ToString();
        }

        
    }

      public   enum   CompareType { Equal, NotEqual, Less, LessOrEqual, Greate, GreateOrEqual, Contains, NoContains, StartWith, EndWith };

  #endregion 

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.Linq.Expressions;
  using   System.Reflection;
  namespace   FIStudio.WinUI.Core
{
      public   class   ExpParser
    {
        
          public  ExpParser(List<Elem>  midfixList)
        {
              this .MidfixList =  midfixList;

        }
          public  List<Elem> PostfixList {  get ;  private   set  ; }
          public  List<Elem> MidfixList {  get ;  private   set  ; }
          private  Stack<Elem> CalcStack =  new  Stack<Elem> ();
          private   void   GuardMidfixListExist()
        {
              if  (MidfixList ==  null  || MidfixList.Count <=  0 )  throw   new  Exception( "  中序列表为null或为空!  "  );
        }
          private   void   EnsurePostfixReady()
        {
              if  (PostfixList ==  null  )
            {
                PostfixList  =  DoParse(MidfixList);
                  if  (PostfixList ==  null  || PostfixList.Count <=  0 )  throw   new  Exception( "  后序列表为null或为空!  "  );
            }
        }
          ///   <summary> 
         ///   判断元素是否符合要求
          ///   </summary> 
         ///   <param name="ent"></param> 
         ///   <returns></returns> 
         public   bool  IsSatisfy( object   ent)
        {
            GuardMidfixListExist();
            EnsurePostfixReady();


            CalcStack.Clear();
              foreach  ( var  item  in   PostfixList)
            {
                  if  (item  is   ExpElem)
                {
                    CalcStack.Push(item);
                      continue  ;
                }
                  #region  And 运算
                 if  (item  is   AndElem)
                {
                      var  op1 = CalcStack.Pop()  as   ExpElem;
                      var  op2 = CalcStack.Pop()  as   ExpElem;

                      //  任意一个是false则直接压入false 
                     if  (op1.Result ==  false  || op2.Result ==  false  )
                    {
                        CalcStack.Push(  new  ExpElem() { Result =  false   });
                          continue  ;
                    }

                      if  (!op1.Result.HasValue && ! op2.Result.HasValue)
                    {
                        op1.Compare(ent);
                          if  (op1.Result.Value ==  false  )
                        {
                            CalcStack.Push(  new  ExpElem() { Result =  false   });
                              continue  ;
                        }
                        op2.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op2.Result });
                          continue  ;
                    }
                      if  (!op1.Result.HasValue && op2.Result ==  true  )
                    {
                        op1.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op1.Result });
                          continue  ;
                    }
                      if  (op1.Result ==  true  && ! op2.Result.HasValue)
                    {
                        op2.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op2.Result });
                          continue  ;

                    }
                      if  (op1.Result ==  true  && op2.Result ==  true  )
                    {
                        CalcStack.Push(  new  ExpElem() { Result =  true   });
                          continue  ;
                    }

                }
                  #endregion 
                 #region  Or 运算
                 if  (item  is   OrElem)
                {
                      var  op1 = CalcStack.Pop()  as   ExpElem;
                      var  op2 = CalcStack.Pop()  as   ExpElem;

                      //  任意一个是true则直接压入true 
                     if  (op1.Result ==  true  || op1.Result ==  true  )
                    {
                        CalcStack.Push(  new  ExpElem() { Result =  true   });
                          continue  ;
                    }

                      if  (!op1.Result.HasValue && ! op2.Result.HasValue)
                    {
                        op1.Compare(ent);
                          if  (!op1.Result ==  true  )
                        {
                            CalcStack.Push(  new  ExpElem() { Result =  true   });
                              continue  ;
                        }
                        op2.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op2.Result });
                    }
                      if  (!op1.Result.HasValue && op2.Result ==  false  )
                    {
                        op1.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op1.Result });
                          continue  ;
                    }
                      if  (op1.Result ==  false  && ! op2.Result.HasValue)
                    {
                        op2.Compare(ent);
                        CalcStack.Push(  new  ExpElem() { Result =  op2.Result });

                          continue  ;
                    }
                      if  (op1.Result ==  false  && op2.Result ==  false  )
                    {
                        CalcStack.Push(  new  ExpElem() { Result =  false   });
                    }

                }
                  #endregion  
            }
              return  (CalcStack.Pop()  as   ExpElem).Result.Value;

        }
          ///   <summary> 
         ///   生成判断函数
          ///   </summary> 
         ///   <returns></returns> 
         public   Expression<Func<T, bool >> GenIsSatisfyFunc<T> ()
        {
            GuardMidfixListExist();
            EnsurePostfixReady();
            Stack < object > stack =  new  Stack< object > ();

            ParameterExpression entExp  = Expression.Parameter( typeof (T),  "  ent  "  );
              foreach  ( var  elem  in   PostfixList)
            {

                  if  (elem  is   ExpElem)
                {
                    stack.Push(elem);
                      continue  ;
                }
                  if  (elem  is   AndElem)
                {
                      var  elem1 =  stack.Pop();
                      var  elem2 =  stack.Pop();

                      var  exp=  Expression.AndAlso(GetCallExpression(elem1,entExp),GetCallExpression(elem2,entExp));
                    
                    stack.Push(exp);
                      continue  ;
                }
                  if (elem  is   OrElem)
                {
                      var  elem1 =  stack.Pop();
                      var  elem2 =  stack.Pop();

                      var  exp=  Expression.OrElse(GetCallExpression(elem1,entExp),GetCallExpression(elem2,entExp));
                    
                    stack.Push(exp);
                      continue  ;
                }
            }
            LambdaExpression lambda = Expression.Lambda<Func<T, bool >>( stack.Pop()  as   Expression,entExp);

              return  lambda  as   Expression<Func<T, bool >> ;

        }
          private  Expression GetCallExpression( object   elem, ParameterExpression entExp)
        {
              if  (elem  is   ExpElem)
            {
                 return  Expression.Call(Expression.Constant(elem),  typeof (ExpElem).GetMethod( "  Compare  "  ), entExp);
            }
              return  elem  as   Expression;
        }
          ///   <summary> 
         ///   中序表达式转后缀表达式
          ///   </summary> 
         ///   <param name="midfix"></param> 
         ///   <returns></returns> 
         private   List<Elem> DoParse(List<Elem>  midfix)
        {
            Stack <Elem> stack =  new  Stack<Elem> ();
              var  list= new  List<Elem> ();
              foreach  ( var  elem  in   midfix)
            {
                  if  (elem  is   ExpElem)
                {
                    list.Add(elem);
                      continue  ;
                }
                  if  (elem  is   LBElem)
                {
                    stack.Push(elem);
                      continue  ;
                }
                  if  (elem  is   RBElem)
                {
                      var  e =  stack.Pop();
                      while  (!(e  is   LBElem))
                    {
                        list.Add(e);
                        e  =  stack.Pop();
                      

                    }
                      continue  ;
                }
                  if ((elem  is  AndElem) || (elem  is   OrElem))
                {
                      if  (stack.Count >  0  )
                    {
                          var  e =  stack.Peek();
                          while  ( !(e  is  LBElem) && elem.Priority <=  e.Priority)
                        {
                            list.Add(stack.Pop());
                              if  (stack.Count <=  0 )  break  ;
                            e  =  stack.Peek();
                        }
                    }
                    stack.Push(elem);
                }

            }
              while  (stack.Count >  0  )
            {
                list.Add(stack.Pop());
            }

              return   list;

        }
    }
      #region  节点定义
     public   class   Elem
    {
          public   virtual   string  Name {  get ;  set  ; }
          public   virtual   int  Priority {  get ;  set  ; }
          public  Object Data {  get ;  set  ; }
    }
      ///   <summary> 
     ///   左括号
      ///   注意stack中只会压入'(','And','Or'
      ///   </summary> 
     public   class   LBElem : Elem
    {
          public   override   string   Name
        {
              get  
            {
                  return   "  (  "  ;
            }
        }
          public   override   int   Priority
        {
              get  
            {
                  return   59  ;
            }
        }
    }
      ///   <summary> 
     ///   右括号
      ///   </summary> 
     public   class   RBElem : Elem
    {
          public   override   string   Name
        {
              get  
            {
                  return   "  )  "  ;
            }
        }
          public   override   int   Priority
        {
              get  
            {
                  return   99  ;
            }
        }

    }

      public   class   AndElem : Elem
    {
          public   override   string   Name
        {
              get  
            {
                  return   "  And  "  ;
            }
        }
          public   override   int   Priority
        {
              get  
            {
                  return   88  ;
            }
        }
    }

      public   class   OrElem : Elem
    {
          public   override   string   Name
        {
              get  
            {
                  return   "  Or  "  ;
            }
        }
          public   override   int   Priority
        {
              get  
            {
                  return   77  ;
            }
        }
    }
      public   class   ExpElem : Elem
    {

          public   override   int   Priority
        {
              get  
            {
                  return   66  ;
            }
        }
          public   bool  Compare( object   ent)
        {
            Console.WriteLine(  "  计算了:  "  +  Name);
              bool ? ret= null  ;
              if  (AssertType ==  Core.CompareType.Equal)
            {
                ret =  string .Compare(GetV(ent),Value, true )== 0  ;
            }
              if  (AssertType ==  Core.CompareType.NotEqual)
            {
                ret  =   string .Compare(GetV(ent), Value,  true ) !=  0  ;
            }
              if  (AssertType ==  Core.CompareType.Greate)
            {
                ret  =  string .Compare(GetV(ent), Value,  true ) >  0  ;
            }
              if  (AssertType ==  Core.CompareType.GreateOrEqual)
            {
                ret  =  string .Compare(GetV(ent), Value,  true ) >=  0  ;
            }
              if  (AssertType ==  Core.CompareType.Less)
            {
                ret  =  string .Compare(GetV(ent), Value,  true ) <  0  ;
            }
              if  (AssertType ==  Core.CompareType.LessOrEqual)
            {
                ret  =  string .Compare(GetV(ent), Value,  true ) <=  0  ;
            }
              if  (AssertType ==  Core.CompareType.Contains)
            {
                ret  =  GetV(ent).Contains(Value);
            }
              if  (AssertType ==  Core.CompareType.NoContains)
            {
                ret  =!  GetV(ent).Contains(Value);
            }
              if  (AssertType ==  Core.CompareType.StartWith)
            {
                ret  =  GetV(ent).StartsWith(Value);
            }
              if  (AssertType ==  Core.CompareType.EndWith)
            {
                ret  =  GetV(ent).EndsWith(Value);
            }
              if  (!ret.HasValue)  throw   new  Exception( "  未知的CompareType!  "  );
            Result  =  ret;
              return   ret.Value;

           
        }
          public   bool ? Result {  get ;  set  ; }
          public  PropertyInfo Property {  get ;  set  ; }
          public  CompareType AssertType {  get ;  set  ; }
          public   string  Value {  get ;  set  ; }

          private   string  GetV( object   ent)
        {
              var  tmp= Property.GetValue(ent,  null  );
              if  (tmp ==  null ) tmp =  string  .Empty;
              return   tmp.ToString();
        }

        
    }

      public   enum   CompareType { Equal, NotEqual, Less, LessOrEqual, Greate, GreateOrEqual, Contains, NoContains, StartWith, EndWith };

  #endregion  

} 

参考:

  逆波兰式构建方法

  1、从左至右扫描一中缀表达式。
                2、若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈
                3、若读取的是运算符
                   (1) 该运算符为左括号"(",则直接存入运算符堆栈。
                   (2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止,此时抛弃该左括号。
                   (3) 该运算符为非括号运算符:
                       (a) 若运算符堆栈栈顶的运算符为左括号,则直接存入运算符堆栈。
                       (b) 若比运算符堆栈栈顶的运算符优先级高,则直接存入运算符堆栈。
                       (c) 若比运算符堆栈栈顶的运算符优先级低或相等,则输出栈顶运算符到操作数堆栈,
                            直至运算符栈栈顶运算符低于(不包括等于)该运算符优先级,或为左括号,并将当前运算符压入运算符堆栈。
                4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。

   逆波兰表达式求值算法:

               1、循环扫描语法单元的项目。
               2、如果扫描的项目是操作数,则将其压入操作数堆栈,并扫描下一个项目。
               3、如果扫描的项目是一个二元运算符,则对栈的顶上两个操作数执行该运算。
               4、如果扫描的项目是一个一元运算符,则对栈的最顶上操作数执行该运算。
               5、将运算结果重新压入堆栈。
               6、重复步骤2-5,堆栈中即为结果值。

  资源

字符串公式解析器——使用“逆波兰式算法”及C#实现

 

 

标签:  EF ,  布儿表达式解析

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于List<T>列表通用过滤的详细内容...

  阅读:48次