您的位置:首页 > 其它

介绍TemplateEngine

2007-12-08 12:46 197 查看
***************图书推荐*************************************************************************************




21.7 元



26.9 元



38.3 元



23.9 元



71.3 元



16.6 元
*********************************************************************************************************************

来源:Lostinet http://www.cnblogs.com/Lostinet/archive/2007/12/07/987122.html

TemplateEngine它不是一个产品的名字.它只是我的MVC框架中的一个子部分.

这个引擎负责把对象数据呈现成文本数据.

它有一些特征:

1. 指令简单 - 内置不超过10个常用的指令.
2. 基于XPath - 直接使用XPath查找对象,并且可以使用XPath强大的语法和函数.
3. 容易扩展 - 无论是指令还是XPath函数都可以自定义.
4. 解析超快 - 基于其语法特点,解析模板结构非常快.

它使用了一个叫 LateBindingNavigator 的工具类, 用于支持使用XPath去查询对象的属性.

使用XPath是个优点 , 同时也是个缺点. 因为开发人员必须熟悉XML,并且学习XPath知识. (例如曾经使用过XSLT)

下面介绍一下它的基础语法:

就像ASP的<%%>类似 ,
TemplateEngine选择了使用'{'和'}'作为模板指令的开始和结束.
而'{'之后,必须接一个符号'#','=','^','~'.

例如:
1.
<img src="{~/images/logo.gif}"/>
2.
<title>{=/Controller/Title}</title>
3.
{# include Includes/Bottom.htm }
4.
<div>{^ MyService:HtmlEncodeWithBR(Content) }</div>

如果'{'后面不接以上列出的符号 , 那么它就不是TemplateEngine的指令块.
这个是为了防止常规使用{}的情况.
例如以下HTML代码不会和TemplateEngine有冲突:
<script>
function window_onload()
{
try{$("usernamebox").focus()}catch(x){}
}
</script>

使用{#...},{=...},{^...},{~...}的设计,可以很方便TemplateEngine的Parser的分析工作.
因为Parser可以很简单地查找出'{',然后分析下一个字符是否符合上面列出的符号,然后再找出'}'就OK了.
由于分析工作实在简单, TemplateEngine的分析性能是非常高的.

而这4个符号的意义分别是:

'#' 指令符号. #后必须跟着一个指令. 这些指令有if,foreach,等等..
写法是 {# 指令 指令参数} 文章后面会说明常用的指令

'~' 根目录符号. 用于生成URL. 例如如果网站的目录不是/,而是IIS下的子目录,例如/MyApp,
那么 <img src="{~/images/logo.gif}"/> 就会生成 <img src='/MyApp/images/logo.gif"/>

'=' 输出符号. 用于直接输出一个值 这个值是HtmlEncode后再输出的.
写法是 {=XPath语句} 例如 {=/HttpContext/Request/Url/PathAndQuery}

'^' 输出符号. 直接不经过HtmlEncode就输出原始的值. 这个用于输出HTML的内容的.
例如 {^MyService:GenerateUserLinkHTML(/Controller/Article/User) }

另外 {..} 结构还可以被注释起来 , 例如:
<ul>
<!--{#foreach /Controller/BlogItems/Item}-->
<li><a href='{~/BlogArticle.Aspx?ArticleId}={=ArticleId}'>{=Title}</a></li>
<!--{#end}-->
</ul>
实际指令仍然会运作, 不过注释起来后, '<!--'和'-->' 就不会输出了.
这样的好处是如果切换到设计视图,这些指令就会隐藏起来.不会太影响设计的效果.
通常这个用在 if,else,elseif,foreach,select,end 指令上. 这些指令属于block指令.

如果要使用TemplateEngine,可以使用以下的C#代码:

//初始化
string file=Server.MapPath("myview.htm");
//包含了用户自定义的扩展 , 例如自定义的#指令
MyTemplateService service=new MyTemplateService();
//把一个类的静态方法变成XPath里的 MyService:Xxxx() 函数
service.SetExtension("MyService",typeof(MyService));
//把一个对象的非静态方法变成XPath里的 Controller:Xxxx() 函数
service.SetExtension("Controller",this);
ITemplateTransform transform=TemplateDocument.CreateTransform(file,null,service);
transform.Init();//通常这个在OnInit的时候做.

//输出数据
Dictionary<string, object> roots=new Dictionary<string, object>();
//把对象变成XPath下的 /HttpContext
roots.Add("HttpContext",Context);
roots.Add("Controller",this);
//...更多的根对象
LateBindingNavigator navigator=new LateBindingNavigator(roots);
//把根对象传入Execute方法中,输出到writer去.
transform.Execute(writer,navigator);

就这样,视图文件,自定义方法,自定义的数据,就会汇集在一块, 在Execute的过程中, 生成结果,写进 writer 去.

roots.Add("HttpContext",Context);
roots.Add("Controller",this);
这个非常重要. 因为它定义了数据的根. 在myview.htm里 , 就可随时使用它们: 例如
<table>
<thead>
<tr>
<td>Key</td><td>Value</td>
</tr>
</thead>
<tbody>
<!--{#foreach /HttpContext/Request/Params/Item}-->
<tr>
<td>{=Key}</td><td>{=Value}</td>
</tr>
<!--{#end}-->
</tbody>
</table>
如果Controller中自定义了某些属性,
public string Message
{
get
{
return _message;
}
}
也可以直接调用:
<div class="message">
{=/Controller/Message}
</div>

XPath语法:

XPath的具体语法 , 可以参考XMLSDK, 例如去搜索引擎查找 'xmlsdk.chm' , 就会有相关的XPATH介绍.
用过XSL的人对XPATH会比较熟悉的. 实际上TemplateEngine的指令也比较接近XSL.

LateBindingNavigator中定义了一些元素的规则.

例如
Property规则:
使用一个属性名称作为NodeName,可以返回该属性的指,例如
<!--{#if /HttpContext/User/Identity/IsAuthenticated}-->
你已经登陆!
<!--{#end}-->
相当于HttpContext.User.Identity.IsAuthenticated

Item规则
当对象是ICollection的时候,自动生成Item用于检索每一个元素.
例如常规
{=/HttpContext/Request/QueryString/Count}可得到有多少个URL参数
而这个
<!--{#foreach /HttpContext/Request/QueryString/Item}-->
{#comment 当前'.'为string }
{=.}
<!--{#end}-->
则循环ICollection的一项

@Key规则
使用@Key可以直接执行this["Key"]返回对象,
例如
{=/HttpContext/Request/QueryString/@PageSize}

可扩展的规则:
例如
{=/HttpContext/GetHashCode}
GetHashCode它原本是个方法,但是经过LateBindingNavigator变成一个扩展的属性.
开发人员可以通过实现ILateBindingNavigatorProvider来自定义扩展的属性.
例如,如果喜欢的话,可以扩展一下日期:
页面访问时间 : {^/HttpContext/Timestamp/LocalTimeHTML}

TemplateEngine的常用指令:

#include指令 - {#include 文件相对路径}
这个指令很重要,因为它允许包含其他的文件.
例如
<!--{#include Header.htm}-->
....
<!--{#include Footer.htm}-->

#end指令
当使用了#select,#if,#foreach这些block指令后,必须使用{#end}来表示结束.

#select指令 - {#select XPathExp}
这个指令用于跳转到某个对象,用于减少代码,和提高查询的性能:
例如不用#select:
Title:{=/Controller/Article/Title}
User :<a href='{~/profile.aspx?UserId}={=/Controller/Article/User/UserID}'>{=/Controller/Article/User/UserName}</a>
Content : {=/Controller/Article/Content}

使用了#select之后:
<!--{#select /Controller/Article/}-->
Title:{=Title}
<!--{#select User}-->
User :<a href='{~/profile.aspx?UserId}={=UserID}'>{=UserName}</a>
<!--{#end}-->
Content : {=Content}
<!--{#end}-->

#select还有一个特点, 如果该对象找不到,那么就会跳过对应的{#end}里的内容.

#if,#else,#elseif指令 - {#if XPathExp} {#else} {#elseif XPathExp}
这些指令用于基本的条件判断.
条件成立的情况是XPathExp存在着结果,并且第一个结果不是null或者bool的false
例如
<!--{#if /HttpContext/Request/QueryString/@HideDetails!='1'}-->
<div class="details">{#include details.htm}</div>
<!--{#end}-->

#foreach指令
这个指令用于循环集合(数组)或者字典.
对于ICollection的实现,需要循环Item元素:
<!--{#foreach /HttpContext/Request/UserLanguages/Item}-->
{=.}
<!--{#end}-->

对于IDictionary类型的,则Item表示循环KeyValuePair:
<!--{#foreach /HttpContext/Request/Cookies/Item}-->
{=Key}={=Value}
<!--{#end}-->

当然可以直接循环Values:
<!--{#foreach /HttpContext/Request/Cookies/Item/Value}-->
{=Path}{=Name}
<!--{#end}-->

#continue , #break 指令
用于中断#foreach指令的循环.

#dir指令
用于表示当前目录.
例如
<img src='{#dir}/images/icon.gif' />

#design指令
这个是一个block指令,用于插入设计时的代码,或者是注释 ,
例如
<!--{#design}-->
<link rel=stylesheet href='design.css' />
<!--{#end}-->

#design指令的内容会直接忽略.

#comment指令
和#design用意一样, 不过这个不是block指令,不需要#end 例如
<!--{#comment 客户端看不到的注释}-->

扩展的指令:

{#render 控件ID}
这个指令直接把对应的控件的值Render出来.
它是MVC的核心指令.
因为它的存在, 让我的MVC完全兼容控件的生命周期, 并且完美地和ASP.NET AJAX兼容.

{#loadascx Ascx文件}
这个指令加载一个用户控件,并且把控件Render出来.

TemplateEngine的基本用法就介绍到这里了.
它还只是一个构造中的方案.
我也正在拿它来做一些小项目,积累一些经验,然后改进它.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: