C#笔记:用Expressions表达式自动生成linq查询

2019-11-22 09:46:05 浏览数 (2)

代码语言:javascript复制
string[] companies = { "Consolidated Messenger", "Alpine Ski House", "Southridge Video", "City Power & Light",
                               "Coho Winery", "Wide World Importers", "Graphic Design Institute", "Adventure Works",
                               "Humongous Insurance", "Woodgrove Bank", "Margie's Travel", "Northwind Traders",
                               "Blue Yonder Airlines", "Trey Research", "The Phone Company",
                               "Wingtip Toys", "Lucerne Publishing", "Fourth Coffee" };
           
            IQueryable<String> queryableData = companies.AsQueryable<string>(); 
            //首先,要把需要查询的数据源先准备好
            
            ParameterExpression pe = Expression.Parameter(typeof(string), "company");
            //我们可以把它当作 linq lambda式中的一个常量,比如 company=>company
           
            Expression left = Expression.Call(pe, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
            //执行完这句,我们得到了一个式子 company.ToLower(),前面的常量发挥了作用
            
            Expression right = Expression.Constant("coho winery");
            //我们得到了一个string类型的变量 coho winery
            
            Expression e1 = Expression.Equal(left, right);
            //我们得到了 company.ToLower() == "coho winery"
            
            left = Expression.Property(pe, typeof(string).GetProperty("Length"));
            // pe 就是简单的常量 company ,这句就是 company.Length
            
            right = Expression.Constant(16, typeof(int));
            // 16
            
            Expression e2 = Expression.GreaterThan(left, right);
            // company.Length > 16
            
            Expression predicateBody = Expression.OrElse(e1, e2);
            //  company.ToLower() == "coho winery" || company.Length > 16
    
            //接下来就耐人寻味了
            MethodCallExpression whereCallExpression = Expression.Call(
                typeof(Queryable),  
                //我们要查的元素是Queryable 类型
                
                "Where", 
                //Queryable 类型中有个Where方法
                
                new Type[] { queryableData.ElementType }, 
                //这个指的是Where<T> 中的T应该为什么元素,显然下面的OrderBy函数 其实是OrderBy<TSource, TKey>。必须指定type
                
                queryableData.Expression, 
                //这个可以简单理解为是什么东西(的方法簇)需要调用Where方法。显然是我们指定的data需要。
                
                Expression.Lambda<Func<string, bool>>(predicateBody, new ParameterExpression[] { pe }
                //传入的是一个lambda表达式。这个比较耐人寻味。传入的是company,显然是string类型。
                //company.ToLower() == "coho winery" || company.Length > 16 返回的显然是bool类型的值
                // 至于后面,第二个参数可以想像为 => 左边的东西。第一个参数是表达式,在 =>右边。
            ));
        
            // 简单说来就是,先指定调用method的源的类型。
            //再指定method的方法名。
            //再指定这个方法如果是泛型,需要传入的类型type
            //再指定源的实体
            //再指定传入参数的实体。这样一个MethodCallExpression就生产出来了。好了该睡觉了。
            
            MethodCallExpression orderByCallExpression = Expression.Call(
                typeof(Queryable),
                "OrderBy",
                new Type[] { queryableData.ElementType, queryableData.ElementType },
                whereCallExpression,
                Expression.Lambda<Func<string, string>>(pe, new ParameterExpression[] { pe }));
          
          
            IQueryable<string> results = queryableData.Provider.CreateQuery<string>(orderByCallExpression);
          
            foreach (string company in results)
                Console.WriteLine(company);

0 人点赞