目录
.Net4 Expression Tree 入门(1): Hello World!
.Net4 Expression Tree 入门(2): IfThen, SwitchCase
.Net4 Expression Tree 入门(3): Loop 循环
前面已经介绍了.Net4 Expression Tree的分支与循环,是时候综合起来写一个稍微复杂一点的实例了。
static List<int> GetPrimes_SimpleMethod(int to) { var res = new List<int>(); for (int n = 2; n <= to; n++) { bool found = false; for (int d = 2; d <= Math.Sqrt(n); d++) { if (n % d == 0) { found = true; break; } } if (!found) res.Add(n); } return res; }
暂且不用考虑以上算法的时间复杂度、性能什么的,因为只是为了学习 Expression Tree 而已。之前都说过,Expression 里是没有For这些常用方法的,只有Loop,因此为了更方便构造 Expression Tree, 需要对上面代码稍微修改成没for的形式。
如
for (int n = 2; n <= to; n++) { // do sth… }
改成 while形式:
int n = 2; while (true) { if (!(n <= to)) break; // do sth… n++; }
【纯粹是为了更方便构造 Expression Tree,否则相信没人用while(true)这样写法】
static List<int> GetPrimes_NoFor(int to) { var res = new List<int>(); int n = 2; while (true) { if (!(n <= to)) break; bool found = false; int d = 2; while (true) { if (!(d <= Math.Sqrt(n))) break; if (n % d == 0) { found = true; break; } d++; } if (!found) res.Add(n); n++; } return res; }
最终构建表达式的代码很长,有兴趣的不妨自己试着写写,这里不贴上来,可以参考这篇外文 《STATEMENT TREES WITH LESS PAIN – FOLLOW-UP ON SYSTEM.LINQ.EXPRESSIONS V4.0》。
你是否也因为Expression 里没有for这个方法而感到不爽?一切循环都得改成loop这种形式?Expression构建是不是很麻烦罗嗦?为什么Expression一切方法皆是static的…等等。
如果改成下面这种形式会不会好点?
这样会不会更简洁?欢迎作进一步交流。我会在下一篇随笔里分析如何实现以上形式的写法。
为什么我需要 Expression Tree?
它有什么好处?
实际项目中有可能用到它么?
它可以应用在哪些地方?
… …
以上是很多不认识Expression Tree,或刚接触不久的童鞋们所困惑的问题。实际上,上面这些问题在他们心中只是归纳成一个问题——Expression Tree 值不值得我去学?
于是乎,大多数技术诞生时都会伴随着Showcase,Getting Started,Tutorial,Sample Application等。大学某些导师就是没有得这一窍门,在开课的第一天没有花时间去展示他所教导的课程的Showcase,以至于童鞋们感到very boring,没有动力学下去。关于这一点,当初教导我编程语言的老师经过一段时间后明白了。她在开课前一个月都是讲语法,什么if else for while 啊,发现童鞋们睡倒一大片。于是,她用她所教导的语言编写了几个图形游戏,如打乒乓球之类的。那一堂课,童鞋们专心多了,而我也知道编程不只用于加减乘除了。
严格来说,Expression Tree 是个低调的家伙,以至于它的光芒被其他上层建筑挡住了,如Linq to SQL。因此,也很难找到能让大家眼前一亮的Showcase,而只能限于代码级别去展示。
var queryBuilder = QueryBuilder.Create<Order>() .Like(c => c.Customer.ContactName, txtCustomer.Text) .Between(c => c.OrderDate, DateTime.Parse(txtDateFrom.Text), DateTime.Parse(txtDateTo.Text)) .Equals(c => c.EmployeeID, int.Parse(ddlEmployee.SelectedValue)) .In(c => c.ShipCountry, selectedCountries);
详见 QueryBuilder : 打造优雅的Linq To SQL动态查询
Linq to Google 示例代码
GoogleContext gc = new GoogleContext(key); var r = from ipods in gc.products where ipods.BaseQuery == "mp3 players" && ipods.Brand == "apple" && ipods.FeedType == "snippets" && ipods.Price < 200 orderby ipods.Price select new { ipods.Title, ipods.Price };
更多 Walkthrough: Creating an IQueryable LINQ Provider
var c = new CodeDomGenerator(); c.AddNamespace("Samples").AddClass("TestClass") .AddMethod(MemberAttributes.Public | MemberAttributes.Static, () => "Print", Emit.stmt(() => Console.WriteLine("Hello, world!")) ); Console.WriteLine(c.GenerateCode(CodeDomGenerator.Language.CSharp)); Console.WriteLine(c.GenerateCode(CodeDomGenerator.Language.VB)); Assembly assembly = c.Compile();
以上示例代码都见不到 Expression Tree 的影子,因为 Expression Tree 是支撑物,默默地成为伟大建筑的一根支柱。
以上示例代码并不是说非用 Expression Tree 不可,底层实现方法有很多,Expression Tree 只是其中一种。
Expression Tree 永远不会孤军作战的, 正如一根支柱不会独立存在那样。