动态构造Lambda表达式

环境:Visual Studio2008 .NET Framework3.5

场合:查询条件不确定,需动态生成

动态构造代码:
 1    /// <summary>
 2    /// 动态构造Lambda表达式
 3    /// </summary>
 4    /// <typeparam name="T">查询目标实体</typeparam>

 5    public class ConstructLambda<T> where T : classnew()
 6    {
 7        private Type TType;
 8        /// <summary>
 9        /// 构造方法
10        /// </summary>

11        public ConstructLambda()
12        {
13            TType = typeof(T);
14        }

15        /// <summary>
16        /// 构造与表达式
17        /// </summary>
18        /// <param name="dictionary">构造源</param>
19        /// <returns>lambda表达式</returns>

20        public Expression<Func<T, bool>> GetAndLambdaExpression(Dictionary<stringstring> dictionary)
21        {
22            Expression expression_return = Expression.Constant(true);
23            ParameterExpression expression_param = Expression.Parameter(TType, "p");
24            foreach (string key in dictionary.Keys)
25            {
26                Expression temp = Expression.Equal(Expression.Call(Expression.Property(expression_param, TType.GetProperty(key)), TType.GetMethod("ToString")),
27                    Expression.Constant(dictionary[key]));
28                expression_return = Expression.And(expression_return, temp);
29            }

30            return (Expression<Func<T, bool>>)Expression.Lambda<Func<T, bool>>(expression_return, new ParameterExpression[] { expression_param });
31        }

32
33        /// <summary>
34        /// 构造或表达式
35        /// </summary>
36        /// <param name="dictionary">构造源</param>
37        /// <returns>Lambda表达式</returns>

38        public Expression<Func<T, bool>> GetOrLambdaExpression(Dictionary<stringstring> dictionary)
39        {
40            Expression expression_return = Expression.Constant(false);
41            ParameterExpression expression_param = Expression.Parameter(TType, "p");
42            foreach (string key in dictionary.Keys)
43            {
44                Expression temp = Expression.Equal(Expression.Call(Expression.Property(expression_param, TType.GetProperty(key)), TType.GetMethod("ToString")),
45                    Expression.Constant(dictionary[key]));
46                expression_return = Expression.Or(expression_return, temp);
47            }

48            return (Expression<Func<T, bool>>)Expression.Lambda<Func<T, bool>>(expression_return, new ParameterExpression[] { expression_param });
49        }

50

实例:
测试数据:
        虚拟实体:
    public class Person
    
{
        
public string Name getset; }
        
public string Sex getset; }
        
public int Age getset; }
        
public DateTime Birthday getset; }

        
public Person()
        
{ }
    }

      虚拟查找源:
        private Dictionary<stringstring> dictionary = new Dictionary<stringstring>() 
        
{
            
{"Name","JT"},{"Sex",""},{"Age","20"},{"Birthday","02/02/2008"}
        }
;

 1,无条件查找:    
new ConstructLambda<Person>().GetAndLambdaExpression(new Dictionary<string, string>()).ToString()返回结果:
p => True

  new ConstructLambda<Person>().GetOrLambdaExpression(new Dictionary<string, string>()).ToString()返回结果:
p => False
 2,多条件查找:
  new ConstructLambda<Person>().GetAndLambdaExpression(dictionary).ToString()返回结果:
p => ((((True And (p.Name.ToString() = "JT")) And (p.Sex.ToString() = "男")) And (p.Age.ToString() = "20")) And (p.Birthday.ToString() = "02/02/2008"))

  new ConstructLambda<Person>().GetOrLambdaExpression(dictionary).ToString()返回结果:
p => ((((False Or (p.Name.ToString() = "JT")) Or (p.Sex.ToString() = "男")) Or (p.Age.ToString() = "20")) Or (p.Birthday.ToString() = "02/02/2008"))

           //构造常量表达式
            Expression expression_return = Expression.Constant(true);
            
//构造表达式参数  类似于p=> 中的p
            ParameterExpression expression_param = Expression.Parameter(TType, "p");
            
//遍历所有关键词 生成查询条件
            foreach (string key in dictionary.Keys)
            
{
                
//生成类似与“p.Name.ToString()==常量”的表达式
                Expression temp = Expression.Equal(
                    
//后面两行先用.Property 得到p.Name 然后用call得到p.Name.ToString();
                    Expression.Call(
                    Expression.Property(expression_param, TType.GetProperty(key)),TType.GetMethod(
"ToString")),
                    Expression.Constant(dictionary[key]));
                
//合并查询条件
                expression_return = Expression.And(expression_return, temp);
            }
Tag标签: 动态,Lambda
posted @ 2008-04-21 19:19 镜涛 阅读(1921) 评论(12)  编辑 收藏 网摘 所属分类: .NET项目开发

  回复  引用  查看    
#1楼2008-04-21 21:03 | Windie Chai(笑煞天)      
先顶,再看。
  回复  引用  查看    
#2楼2008-04-21 21:22 | 抹茶雪域      
前几天我刚写了个构造Lambda表达式实现多关键字或查询的代码~和楼主的代码大致上差不多~感觉好麻烦~还是拼SQL语句来的快~
  回复  引用  查看    
#3楼2008-04-21 23:18 | BrianLei      
@抹茶雪域,镜涛
确实啊,希望不要写着写着,自己过段时间再看,还要想半天。那就不好了。
写代码时,还是要考虑给自己或他人的可读性.

  回复  引用  查看    
#4楼[楼主]2008-04-21 23:46 | 镜涛      
@抹茶雪域
呵呵,拚SQL 就是容易出错,特别是字段特别多的时候,出错了还不容易找到。用linq 插入跟修改差不多,这样可以提炼以下代码。

  回复  引用  查看    
#5楼[楼主]2008-04-21 23:48 | 镜涛      
@BrianLei
呵呵,写代码总比改代码容易,虽然说用命名良好的变量、方法名作注释是极限,不过必要的注释我感觉还是必要的。毕竟可读性也是代码的一个标准阿!

  回复  引用    
#6楼2008-04-22 01:25 | 路人小刀[未注册用户]
可不可以理解为你在动态构造Sql语句的C#形式的表达?
  回复  引用  查看    
#7楼[楼主]2008-04-22 01:57 | 镜涛      
可以看成是用C#封装了的Sql,最终会被.NET编译器转化成Sql语句来执行。
  回复  引用  查看    
#8楼2008-04-22 08:33 | 李战      
http://www.cnblogs.com/Emoticons/qface/055243188.gif" alt="" />先收下,谢谢!


俺拿回家在慢慢琢磨,现在还看不懂http://www.cnblogs.com/Emoticons/qface/055243523.gif" alt="" />

  回复  引用  查看    
#9楼2008-04-22 08:43 | 云の世界      
确实是这样,很多时候强类型对于编码是优点,但是
实际应用中有多少系统的查询条件是死的呢?
不过,个人更喜欢ibatis那种方式,直接操作SQL,书写方便直观,
避免了手工拼凑SQL的不方便,同时又兼顾灵活性。
配合代码生成引擎(我把CODESMIT引擎嵌入到工程内)
可以大大提高开发效率。

  回复  引用  查看    
#10楼2008-04-22 11:42 | 小瑞克      
最近打算研究Linq的Provider,先收下,不错
  回复  引用  查看    
#11楼2008-04-22 11:56 | Snowdreams      
我还找过一个Dynamic.cs的文件~也是用于Linq动态查询的~命名空间是System.Linq.Dynamic~不知道是不是原本打算放在.Net 3.5中的~不过感觉也不怎么方便~
  回复  引用  查看    
#12楼[楼主]2008-04-22 12:33 | 镜涛      
@Snowdreams
我也看过那个东东,不过还是感觉自己写的认识的更清楚。看别人的学学原理,然后自己写。呵呵




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1164398




相关文章:

相关链接: