在 2025 收官前,看清 Data + AI 的真实走向,点击查看 BUILD 大会精华版 了解详情
写点什么

Expression Evaluator:一个轻量级的 C#编译器服务

  • 2014-05-08
  • 本文字数:2060 字

    阅读完需:约 7 分钟

尽管.NET 社区热切盼望 Roslyn 的正式版本,但工作还是要继续。所以今天我们来介绍另一个编译器服务—— Expression Evaluator 。虽然其他编译器服务都试图尽可能地全面,但它却独辟蹊径。

InfoQ:你说 C# Expression Evaluator 是一个轻量级库,是什么让它成为一个轻量级的库?什么样的库又是重量级的呢?

Repert Avery:Expression Evaluator 的目标是计算表达式,就此而言我认为它是轻量级的,因为它很小(不到 1M),是自包含的,不依赖于其他非核心库(除了 Antlr),并且功能独特。我认为 Roslyn 是重量级的,因为它需要很多库的支持。当然,每个库都有自己的目标,很多 Roslyn 能做的事 Expression Evaluator 可能永远都做不到,如编译整个程序集。但就计算小的表达式来说,我相信 Expression Evaluator 已经做得非常好了。

InfoQ:Antlr 是什么?你为什么会将它包含在库里?

Rupert: Antlr (“又一个语言识别工具”的缩写)是一个最初用 Java 编写的库,可以根据特殊的语法(文法)来构建复杂的解析器代码。它就像是一个用于语言解析的加强版的正则表达式。你可以编写某种语言的语法规则,Antlr 会为你生成代码。

在使用 Antlr 之前我自己编写了这个解析器,它能做一个表达式解析器所需要的所有基础的工作。我能够支持“a + b.method(c,d[e] == f)”这样的表达式。它的规则十分简单。但当我想支持 Lambda 语法时,一切就变得复杂起来。例如表达式“(a,b) => a==b”,(a,b) 应该先解析为参数列表,然后再解析 Lambda 符号 => 之后的所有内容(可能为块表达式),这难倒了我。我需要进行一些回溯并抛弃生成的 token。我那手写的解析器显然无法完成这个任务。

Antlr 让一切变得简单。它能让我关注于编写处理各种语言的代码,而不用操心用于解析的代码。

必须为我正使用的语法文件的作者点赞。我在 https://antlrcsharp.codeplex.com/ 找到了这个十分完整的 C# 4.0 语法文件,我所要做的,就是对每种情况编写代码,来生成适当的表达式。

InfoQ:文档中提到了 LINQ 表达式树。能详细说说你是如何使用的吗?

Rupert:LINQ 表达式能将解析好的表达式存储为某种数据结构。与其自己构建数据结构,不如使用.NET Framework 提供的结构。表达式树还有一个优势是可以编译为.NET 函数。当表达式被编译为实际的.NET CLR 代码后,就可以通过调用该函数来计算表达式。预编译代码的好处是速度的提升。其他不使用 LINQ 表达式的库,在计算表达式时,会遍历等价的表达式树,通过执行代码来模拟正在执行的代码,这是一笔巨大的开销。

比如这样的表达式:

x == a + b

它的表达式树可能为:

根:

节点类型:Equals

左子节点: 参数表达式 x

右子节点: (加法表达式)

加法表达式:

节点类型:Add

左子结点:参数表达式 a

右子节点:参数表达式 b

这在 C#中可以写成:

Expression.Equals(Expression.Parameter('x'), Expression.Add(Expression.Parameter('a'), Expression.Parameter('b'));Expression Evaluator 接下来(使用 Antlr)解析该表达式,生成适当的表达式树。构建完表达式树之后,可以通过 LINQ 将其编译为函数。使用这个库的应用程序可以执行这个函数,就像它已经在第一时间被编译过了一样。被编译为函数之后,表达式树就不再需要了,不过我们可以用它来分析表达式,我相信肯定会有人想要枚举表达式所用到的变量或属性。由于表达式树记录了每个表达式的类型,因此是可以通过这种方式提取这些信息的。

InfoQ:假设我们在编写一个客户端 - 服务器系统。我们需要从客户端向服务器发送搜索条件(如 where 子句)。你会对这样的系统使用这个库吗?如果会,那么将是什么样子的?

Rupert:在这种场景下,如果模型复杂,或查询逻辑复杂,并且客户端可以使用字符串自由地定义查询,那么 Expression Evaluator 就非常有用。Expression Evaluator 将工作于服务器端,解析查询并转换为编译后的代码。

我不清楚你所说的“将是什么样子”是指什么,不过使用了 Expression Evaluator 的 Web 应用程序可以让用户使用代码来定义查询,给用户提供一个可访问的参数集合,用户可以用 C#代码来编写查询,并将原封不动地发送给服务器进行解析和编译。

如果查询需要大量条件代码并且需要考虑性能,这将是 Expression Evaluator 发挥最大作用的时候。与其在查询中使用大量分支条件,不如基于必要的条件构建一个字符串表达式,并将其编译为可在查询中运行的委托。

使用 LINQ 表达式树并没有将其局限于只能为 LINQ 表达式构建动态 where 子句。Expression Evaluator 还可用于数据绑定。此时,用一个 XML 文件存储布局,并使用特性和特殊的符号来标记该文本用于数据绑定,而不是纯文本。XML 元素模仿 HTML,双花括号的符号模仿 AngularJS。结果就是一个很像 HTML/AngularJS 的布局和模板引擎,输出的是 PowerPoint 幻灯片。布局引擎为开发者提供了 HTML 的灵活性,而 Expression Evaluator 允许数据绑定到布局上并控制布局,在 PowerPoint 中生成丰富的报告。

Expression Evaluator 在 CodePlex 上以 Simplified BSD 协议开源。

原文链接: Expression Evaluator: A Lightweight C# Compiler Service

2014-05-08 08:286789
用户头像

发布了 59 篇内容, 共 26.8 次阅读, 收获喜欢 3 次。

关注

评论

发布
暂无评论
发现更多内容

“链”上普洱,云南省区块链中心走进大美普洱

CECBC

区块链+ “链”上普洱 数字云南 分布式产业

首个区块链金融应用规范出炉,标准先行避免“先污染后治理”

CECBC

技术规范 应用评估规则 话语权 政府积极推进

架构师课程第八周 作业

杉松壁

架构师训练营第八周课后题

Cloud.

一个成都程序猿眼中的成都和天府软件园,先从蚂蚁金服说起…

why技术

程序员 成都 蚂蚁金服

产业区块链一周新动态

CECBC

多项扶持政策 产业研究高涨 学会协会成立 应用频繁落地

Java有效面试题

老大哥

面试

从零开始写一个迷你版的Tomcat

简爱W

【架构师训练营 - 作业 -8】

小动物

周末在家加班开发代扣支付网关!

诸葛小猿

加班

两个单向链表是否存在合并元素

周冬辉

第八周作业

qihuajun

安全系列之——手写JAVA加密、解密

诸葛小猿

对称加密 加密解密 非对称加密 rsa AES

登门槛效应 - 请求帮忙,从小事开始。

石云升

登门槛效应 得寸进尺效应

关于架构的几件小事:架构决策

北风

架构 架构设计 架构师 架构设计原则

java并发系列 :实战篇,微服务日志的伤痛,一并帮你解决掉

南方有乔木兮

ARTS 打卡第 4 周

Scotty

AI与劳模的交点:拼多多农研大赛释放的产业能量

脑极体

数据结构和算法-链表

jason

JVM系列之:String.intern和stringTable

程序那些事

Java JVM GC 常量池 字符串

ARTS-WEEK8

一周思进

ARTS 打卡计划

ARTS 打卡(2020.07.13-2020.07.19)

小王同学

【总结】性能优化2

小胖子

设计数据库

左洪斌

ARTS Week9

时之虫

ARTS 打卡计划

Android | xml和view的那些事

哈利迪

android

Java面试胜经001| 阿里Java面试题118道

BUZHIDAO

面试

Spark 窗口函数 I

马小宝

spark 窗口函数 spark window functions

第八周学习总结

qihuajun

全栈新星 -- Dart

金刚狼

flutter dart 全栈 aqueduct

8week

一叶知秋

Expression Evaluator:一个轻量级的C#编译器服务_C#_Jonathan Allen_InfoQ精选文章