拼接表达式树的原理

简单的表达式树,注释写得很清楚

 1             //假如我们要拼接x=>x.Id==1,假如x的类型为User
 2             
 3             //结果是这样:x=>,x是变量名
 4             var parameterExp = Expression.Parameter(typeof(User), "x");
 5             
 6             //结果是这样:x=>x.Id,这句是为了构建访问属性的表达式
 7             //上面这句第一个参数是你要取属性的对象表达式。
 8             //我们要拼的表达式是x=>x.Id==1,==1这块先不管
 9             //其实就是x=>x.Id,那么其实我们就是对x进行取属性值,而x是parameterExp,
10             //第一个参数是parameterExp
11             //第二个参数好说,就是属性名
12             var propertyExp = Expression.Property(parameterExp, "Id");
13             
14             //结果是··没有结果,构建一个常量表达式,值为1(LINQ的世界,一切皆表达式树)
15             //马上就是关键的一步了
16             var constExp = Expression.Constant(1);
17             
18             //结果是:x=>x.Id==1,这个··还需要解释么,很简单,不是么。创建一个相等的表达式,然后传入左边和右边的表达式
19             //当然到这儿还不能用,还需要继续
20             var body = Expression.Equal(propertyExp, constExp);
21             
22             //这句和第二句是我学的时候最难理解的两个地方。这句是将我们的成果封装成能用的
23             //第一个参数就是我们的成果
24             //第二个参数是实现这个成果所需要的参数,那当然是parameterExp,
25             //然后泛型参数Func<User,bool>就是我们想把这个表达式封装成什么样的东西,
26             //此时,lambda的类型就是Expression<Fun<User,bool>>,这个时候就能用了
27             var lambda = Expression.Lambda<Func<User, bool>>(body, parameterExp);
28             

下面来个复杂的

 1             //假如我们要拼接x=>x.Name.Contains("aaa"),假如x的类型为TEntity
 2 
 3             //结果是这样:x=>,x是变量名
 4             var parameterExp = Expression.Parameter(typeof(TEntity));
 5 
 6             //结果是这样:x=>x.Name,这句是为了构建访问属性的表达式
 7             //上面这句第一个参数是你要取属性的对象表达式。
 8             //我们要拼的表达式是x =>x.Name.Constant("aaa"),.Constant("aaa")这块先不管,其实就是x=>x.Name,
 9             //那么其实我们就是对x进行取属性值,而x是parameterExp,所以第一个参数是parameterExp,
10             //第二个参数好说,就是属性名
11             var propertyExp = Expression.Property(parameterExp, "Name");
12 
13             //因为我们要拼接的表达式中调用了string类型的Username的Contains方法,所以反射获取string类型的Contains方法
14             var containsMethod = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
15 
16             //结果是··没有结果,构建一个常量表达式,值为1(LINQ的世界,一切皆表达式树)
17             //马上就是关键的一步了
18             var constExp = Expression.Constant("aaa");
19 
20 
21             //结果是:x=>x.Name.Contains("aaa"),
22             //第一个参数,是要调用哪个实例的方法,这里是propertyExp,
23             //第二个是调用哪个方法
24             //第三个是参数
25             var containsExp = Expression.Call(propertyExp, containsMethod, constExp);
26 
27             //这句是将我们的成果封装成能用的,第一个参数就是我们的成果,
28             //第二个参数是实现这个成果所需要的参数,那当然是parameterExp,
29             //然后泛型参数Func<TEntity, bool>就是我们想把这个表达式封装成什么样的东西,
30             //此时,lambda的类型就是Expression<Fun<TEntity, bool>>,这个时候就能用了
31             var lambda = Expression.Lambda<Func<TEntity, bool>>(containsExp, parameterExp);
32             //现在可以直接使用创建的类型
33             tempData = tempData.Where(lambda);

猜你喜欢

转载自www.cnblogs.com/yanglang/p/9356254.html