`
wyf
  • 浏览: 426194 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

动态构建Expression表达式树

    博客分类:
  • C#
阅读更多

动态构建Expression表达式树

话说.Net已经发展到4.5了,大家对Lambda和Linq应该比较熟悉了。比如我们要取出产品集合里面SKU以"123"开头的产品集,就可以这么写:
Products=Products.Where(p=>p.SKUCode.StartWith("123"));

 

现下有这么个需求,用户输入以逗号分隔的字符串,求取SKU以分隔的字符串开头的产品集,如用户输入"123,234,456",那么就取出SKU以"123"开头或以"234"开头或以"456"开头的产品集合。于是我计上心头,欲以循环解之,无解。为什么呢?因为这里有个关键字“或”。假如是“并”需求,我们大可信手拈来,如下:

 string[] starts = input.Split(',');
 foreach (string start in starts)
 {
     Products = Products.Where(p => p.SKUCode.StartWith(start));
 }

 对于“或”来说,Linq似乎并没有提供一个明确的方法(比如这里的Where)供我们使用,我想是因为“或”的作用域比较难用程序语言界定,因此一旦使用“或”去联接,那最终的结果可能并不是预期的。若“或”对应的方法是Or,那么循环体内的语句变为Products = Products.Or(p => p.SKUCode.StartWith(start));不知所云。我们想要的其实应该是条件的拼接:

p => p.SKUCode.StartWith(start1) || p.SKUCode.StartWith(start2) || p.SKUCode.StartWith(start3) || ……

可惜Linq同样没有给我们提供动态拼接条件的方便的语法(何为方便,我的想法是同字符串拼接,拼接完毕后可简单快捷地转成可执行的语句。啥,你说Javascript?心里想想就是了,说出来干嘛),不过给了稍稍复杂点的方式。下面是代码: 

/// <summary>
/// 根据条件数据动态生成或连接条件
/// </summary>
/// <typeparam name="TSource">集合项类型</typeparam>
/// <param name="sourcePropertyName">待比较的集合项属性</param>
/// <param name="methodName">方法名称</param>
/// <param name="objs">条件数据</param>
/// <returns></returns>
public static Expression<Func<TSource, bool>> GenerateOrElseConditionWithArray<TSource>(string sourcePropertyName, string methodName, IEnumerable<object> objs)
{
    if (objs != null && objs.Count() > 0)
    {
        var len = objs.Count();
        var p = Expression.Parameter(typeof(TSource), "p");
        var propertyName = Expression.Property(p, sourcePropertyName);
        var body = Expression.Equal(Expression.Call(propertyName, methodName, null, Expression.Constant(objs.First())), Expression.Constant(true));
        for (int i = 1; i < len; i++)
        {
            var pcode = objs.ElementAt(i);
            body = Expression.OrElse(body, Expression.Call(propertyName, methodName, null, Expression.Constant(pcode)));
        }
        Expression<Func<TSource, bool>> orExp = Expression.Lambda<Func<TSource, bool>>(body, p);
        return orExp;
    }
    return null;
}

 现在我们就可以这么实现上述需求:

 
 string[] starts = input.Split(',');
 var codeExp = GenerateOrElseConditionWithArray<Product>("SKUCode", "StartsWith", starts);
 if (codeExp != null)
     Products = Products.Where(codeExp);
 
后记:老外写了一个类,貌似比我的专业多了,Dynamically Composing Expression Predicates.

 

 转载请注明本文出处:http://www.cnblogs.com/newton/archive/2012/12/17/2821159.html

分享到:
评论

相关推荐

    ASP.NET Core中如何使用表达式树创建URL详解

    1.对表达式树的代码进行编辑修改,使表达式树中的代码变成动态代码,根据不同的数据库修改树上的代码逻辑从而达到动态切换数据库查询语句的目的,用表达式树可以动态构建针对不同数据库的查询语句。 2.完成类似反射...

    expression-parser:将数学表达式解析为语法树

    如果您构建自己的编译器,则 AST 非常容易使用——echo 编译器只需要来实现安装$ npm install expression-parser用法安全地执行任意数学表达式并获取为函数生成的原始js &gt; var mkFunc = require ( 'expression-...

    ExpressionParser:算术表达式的解析器和树表示

    算术表达式的解析器和树表示 该程序将递归树表示形式用于算术表达式(复合模式)。 它从输入中读取此类表达式并对其进行解析,就像编程语言的编译器一样。 解析器通过递归下降操作。 一旦存储在树表示中,就可以对...

    ExpressionTree:构建和转储 ExpressionTrees

    表达式树 在这个库中,您可以找到一些将简单表达式树转换为常见字符串符号的转储程序。 什么是表达式树? 以一个简单的代数表达式为例 2 * (100 : (1 + 3)) * (98 - 7) 在评估这个表达式时,我们必须找出哪些...

    xFunc:xFunc是一个简单易用的应用程序,可让您构建数学和逻辑表达式。 它是用C#编写的。 该库包含将字符串转换为表达式(解析器,词法分析器等)的代码。

    该库包含有据可查的代码,可让开发人员将字符串解析到表达式树,并使用lexer,解析器等分析(派生,简化)表达式。 xFunc是一个小型可移植的应用程序,您可以使用它来创建将自动计算的复杂数学表达式。 老师和学生...

    parlot:快速轻巧的解析器创建工具

    下面的示例是一个完整的解析器,它创建一个数学表达式树(AST)。 来源可。 public static readonly Parser &lt; Expression &gt; Expression ; static FluentParser () { /* * Grammar: * expression =&gt; facto

    Remote.Linq:只需LINQ您的远程资源即可。

    远程Linq 分支AppVeyor 特拉维斯CI 代码库编纂CodeFactor 执照main 包裹努吉特我的Remote.Linq Remote.Linq.Async.Queryable Remote.Linq.EntityFramework Remote.Linq.... 特征将LINQ表达式转换为可序列化的表达式树

    abacus-core:算盘表达库

    给定一个表达式,它将构建一个抽象语法树(AST),可以在其上执行操作。 例如,它可以简化它,检查语义错误,对其进行评估或将其翻译成某种语言。 目录 快速开始 对于那些迫不及待想要看到它运行的人,请尝试复制并...

    ASP.NET.4揭秘

    第一部分 构建asp.net页面 第1章 asp.net framework概览2 1.1 asp.net和.net framework5 1.1.1 框架类库5 1.1.2 公共语言运行库10 1.2 asp.net控件11 1.2.1 asp.net控件概览11 1.2.2 html控件12 1.2.3 理解和处理...

    ASP.NET4高级程序设计第4版 带目录PDF 分卷压缩包 part1

    3.3.1 显示控件树 3.3.2 页头 3.3.3 动态控件的创建 3.4 Page类 3.4.1 Session、Application和Cache 3.4.2 Request 3.4.3 Response 3.4.4 Server 3.4.5 User 3.4.6 Trace 3.4.7 访问其他类中...

    asp.net知识库

    ASP.NET 2.0构建动态导航的Web应用程序(TreeView和Menu ) 体验.net2.0的优雅(3) -- 为您的 SiteMap 添加 控制转发功能 GridView控件使用经验 ASP.NET 2.0:弃用 DataGrid 吧,有新的网格控件了! ASP.NET2.0控件...

    ASP.NET4高级程序设计(第4版) 3/3

    3.3.1 显示控件树 78 3.3.2 页头 82 3.3.3 动态控件的创建 82 3.4 Page类 84 3.4.1 Session、Application和Cache 84 3.4.2 Request 85 3.4.3 Response 86 3.4.4 Server 88 3.4.5 User 90 3.4.6 ...

    Java语言基础下载

    正则表示式(Regular expression) 133 StringBuffer类 135 StringBuffer与String的区别 136 集合类的使用 136 实例分析 136 内容总结 153 独立实践 154 第十章:JAVA GUI概述 155 学习目标 155 GUI概述及组成 156 ...

    JAVA面试题最全集

    构建一个connect pool,然后再调用它, 8.j2ee平台与dotnet平台的区别 9.ejb的life cycle 10.session bean 和 entity bean的区别 11.ejb中的transaction机制 12.synchronized (生产者和消费) 13.String 和 ...

Global site tag (gtag.js) - Google Analytics