Zendy

---勿在浮沙筑高台---

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  15 随笔 :: 5 文章 :: 151 评论 :: 16 引用

初次听说CodeSmith是在一篇叫做<每个开发人员现在应该下载的十种必备工具>的文章,起初CodeSmith给我的印象不是吸引人.也是在去年的某一段相对比较空闲的时候,抽空尝试了一下CodeSmith,才发现CodeSmith确实是一个好东西.使用过CodeSmith之后,才发现它的实现原理其实不是很复杂,它从Asp.Net的语法中借鉴了不少,应该说CodeSmith实现了Asp.net一部分功能(从aspx模板生成html脚本)的伪Asp.net,只是CodeSmith额外提供了属性申明的功能.以下是对CodeSmith实现原理的简略概述:
1/  支持<%  %>执行代码块语法  ,与 Asp.net语法一模一样
2/  支持<%= %>内联表达式语法  ,与 Asp.net语法一模一样
3/  支持Code Behind功能(<%@ CodeTemplate %>,与 Asp.net的(<%@ Page %>)类似
4/  支持<script runat="template"> </script>函数代码块功能,  与Asp.net的函数代码块功能<script language="C#" runat="server"></script>类似
5/ 支持属性申明,用于配置模板的属性.  Asp.net语法不支持.

关于CodeSmith如何通过模板生成代码的问题, 我们只要了解一下Asp.net如何通过Aspx文件生成Html脚本的过程就可以明了.其实Asp.net生成Html脚本过程远比CodeSmith复杂的多,因为Asp.net还要呈现ServerControl的Html脚本.而CodeSmith只专注于 "<%  %>执行代码块"  "<%= %>内联表达式"  "<script runat="template"> </script>函数代码块"的文法分析及转换.  该文法分析的逻辑也相对简单(和Asp.net一模一样),具体过程如下:
1/  产生一个类Class1(以模板文件名作为类名),默认从CodeTemplate类继承,如果有Code Behind,那么就从Code Behind标记的父类继承(该父类必须从CodeTemplate类继承)
2/  根据所申明的属性,在Class1中添加相应的属性申明及成员变量代码
3/  把模板文件中的<script runat="template"> </script>函数代码块中的函数体 原封不动的拷贝到Class1中,作为Class1的成员函数
4/  开始生成Class1的核心函数体:__RenderMethod1(System.IO.TextWriter writer, CodeSmith.Engine.Control control),按顺序把模板文件中的<%  %>执行代码块中的代码块(不包括字符'<%' 和'%>')原封不动的移植到__RenderMethod1中,把模板文件中不属于<%  %>执行代码块 及<%= %>内联表达式的Code转换成writer.Write("Code");把模板文件中的<%= %>内联表达式的表达式expression转换成writer.Write(expression).
5/  编译所生成的类Class1
6/  调用类Class1的__RenderMethod1函数,产生实际代码(就好像Asp.net中,Asp.net的运行框架对于每个Request,都产生Html脚本).

通过以上分析,大家就觉得CodeSmith的实现原理相对比较简单,和Asp.net的产生Html脚本的原理基本一致(大家可以比较一下CodeSmith产生的Compiled Source和Asp.net的Page Compilation Source).  到此位置, 就有人会想,如果没有CodeSmith,可否通过Asp.net代替CodeSmith来使用?当然答案是完全肯定的.只是CodeSmith带给我们比较多的便利(比如访问DBSchema功能函数,属性值设置等等,直接编译并生成Code),而使用Asp.net作为代码生成器相对比较复杂(起码要创建一个Web虚拟目录,设计一个Aspx模板文件,用IE请求获得asp.net生成的HTML脚本)并且还要添加一些类似CodeSmith扩展功能,工作量也是不小的,有兴趣的朋友可以尝试一下.

另外补充说明一下在CodeSmith2.6版本中, 编译错误的错误代码行数是指Compiled Source的行数,而不是指原来的模板文件中的行数, 在CodeSmith 3.0中已经是指向原来的模板文件中的行数(这点已经和Asp.net的Page Compilation Source一模一样了, 通过预处理命令:#line实现的  )

一些好的CodeSmith的模板文件可以从http://www.ericjsmith.net/codesmith/forum/default.aspx?f=16&p=1&ord=vd下载...

posted on 2005-04-23 16:59  Zendy  阅读(...)  评论(...编辑  收藏