读书人

从浅到深:自己动手开发模板引擎解

发布时间: 2012-07-19 16:02:19 作者: rapoo

由浅入深:自己动手开发模板引擎——解释型模板引擎(一)

受到群里兄弟们的竭力邀请,终于决定来分享一下.NET下的模板引擎开发技术。本系列文章将会带您由浅入深的全面认识模板引擎的概念、设计、分析和实战应用,一步一步的带您开发出完全属于自己的模板引擎。关于模板引擎的概念,我去年在百度百科上录入了自己的解释(请参考:模板引擎)。老陈曾经自己开发了一套网鸟Asp.Net模板引擎,虽然我自己并不乐意去推广它,但这已经无法阻挡群友的喜爱了!

与置换型模板引擎不同的是,解释型模板引擎包含了一个专用解释器,有了解释器的存在就可以支持一些更加复杂而严谨的语法。熟悉设计模式的朋友此时此刻应该能够回想起来“解释器模式”,它是将一些业务封装成一个或多个命令,然后通过一个复杂的解释器(Interpreter)来解析执行来满足生产需求的。实际上,解释型模版引擎就是一个较为复杂的解释器模式的实现而已。具体到模板引擎技术上来,解释器的工作任务实际上就小了很多。按照数据封装模式的不同,解释型模板引擎分为命令解释器和反射解释器两个大类。

命令解释器

还记得置换型模板引擎中,我们在最后曾经处理了一个较为负载的Label“{CreationTime:yyyy年MM月dd日 HH:mm:ss}”吗?实际上,这个就是命令解释器的一种实现。此Label中的format部分可以看作是CreationTime的一个命令。有了命令,我们可以让Label去做更多的事情,这是显而易见的。

命令也可以理解为指令。

为了更加能够说明这个问题,我们先将我们要处理的模板复杂化一点,如下:

  1. <!--#include file="_Page_Header.shtml" -->
  2. <ul>
  3. <li>博主姓名:陈彦铭</li>
  4. <li>创建日期:{CreationTime:yyyy年MM月dd日 HH:mm:ss}</li>
  5. <li>粉丝数量:{FunsCount:D4}</li>
  6. </ul>
  7. <!--#include file="_Page_Footer.shtml" -->

除了我们已经熟悉的{xxx}标签之外,我们又增加了一个文件包含指令“<!--#include file="_Page_Header.shtml"?-->”。这个指令是标准的SHTML语法,意思就是将其他文档中的模板合并到当前的指令位置,如此我们便可以实现代码重用。尤其对于HTML开发来说,使用SHTML包含语法,还可以在诸如Dreamweaver等IDE中实现“所见即可得”的效果。

关于如何实现包含指令,我们将在后续章节中具体介绍。

反射解释器

接触了指令之后,其实我们还是不够满足,因为到目前为止,我们的模板只能做简单的标签置换,这个相当不给力。比如有些内容我们想让它根据情况输出,那么就需要条件语句的效果,再如我们经常会遇到列表等情况,此时要是能有个迭代语句岂不是很给力?难道我们要编写一堆的Label1、Label2、Label3?

有需求,是好事情!咱们是做技术的,为需求而生,为满足需求而战,没有需求,技术就都只是浮云!

为什么条件语句和迭代语句要使用反射来实现,因为在编写这篇文章之前,老陈已经决定了用反射来实现这些机制,无论您是否喜欢!Hah..

我们再次将模板语法复杂化如下:

 1 <!--#include file="_Page_Header.shtml" -->
2 <ul>
3 <li>博主姓名:陈彦铭</li>
4 <li>创建日期:{CreationTime:yyyy年MM月dd日 HH:mm:ss}</li>
5 <li>粉丝数量:{FunsCount:D4}</li>
6 </ul>
7 <hr />
8 <m:if test="{articles.Count > 0}">
9 <ul>
10 <m:foreach item="article" collection="articles">
11 <li><a href="{article.Url}">[{article.Category}] {article.Title}</a></li>
12 </m:foreach>
13 </ul>
14 </m:if>
15 <!--#include file="_Page_Footer.shtml" -->

现在有木有感觉到某种给力呢?虽然这不是最给力的……

概念

虽然,我们只增加了两种语法,而且不多,看起来也貌似并不复杂,但这背后将会牵扯到方方面面的问题,代码解析的难度进一步增加。我们有必要了解一下后面可能使用到的一些概念。

读书人网 >Web前端

热点推荐