介绍TemplateEngine

***************图书推荐*************************************************************************************


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.

2.
{=/Controller/Title}
3.
{# include Includes/Bottom.htm }
4.

{^ MyService:HtmlEncodeWithBR(Content) }

如果'{'后面不接以上列出的符号 , 那么它就不是TemplateEngine的指令块.
这个是为了防止常规使用{}的情况.
例如以下HTML代码不会和TemplateEngine有冲突:

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

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

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

'~' 根目录符号. 用于生成URL. 例如如果网站的目录不是/,而是IIS下的子目录,例如/MyApp,
那么 就会生成 写法是 {=XPath语句} 例如 {=/HttpContext/Request/Url/PathAndQuery}

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


另外 {..} 结构还可以被注释起来 , 例如:


实际指令仍然会运作, 不过注释起来后, '' 就不会输出了.
这样的好处是如果切换到设计视图,这些指令就会隐藏起来.不会太影响设计的效果.
通常这个用在 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 roots=new Dictionary();
//把对象变成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里 , 就可随时使用它们: 例如


 
 
  
 
 
 
 
 
  
 
 
 
KeyValue
{=Key}{=Value}

如果Controller中自定义了某些属性,
public string Message
{
 get
 {
  return _message;
 }
}
也可以直接调用:

{=/Controller/Message}

 

XPath语法:

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

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

例如
Property规则:
使用一个属性名称作为NodeName,可以返回该属性的指,例如

你已经登陆!

相当于HttpContext.User.Identity.IsAuthenticated

Item规则
当对象是ICollection的时候,自动生成Item用于检索每一个元素.
例如常规
{=/HttpContext/Request/QueryString/Count}可得到有多少个URL参数
而这个

{#comment 当前'.'为string }
{=.}

则循环ICollection的一项

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


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


TemplateEngine的常用指令:

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

....

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

#select指令 - {#select XPathExp}
这个指令用于跳转到某个对象,用于减少代码,和提高查询的性能:
例如不用#select:
Title:{=/Controller/Article/Title}
User :{=/Controller/Article/User/UserName}
Content : {=/Controller/Article/Content}

使用了#select之后:

Title:{=Title}

User :{=UserName}

Content : {=Content}

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

#if,#else,#elseif指令 - {#if XPathExp} {#else} {#elseif XPathExp}
这些指令用于基本的条件判断.
条件成立的情况是XPathExp存在着结果,并且第一个结果不是null或者bool的false
例如

{#include details.htm}

#foreach指令
这个指令用于循环集合(数组)或者字典.
对于ICollection的实现,需要循环Item元素:

{=.}

对于IDictionary类型的,则Item表示循环KeyValuePair:

{=Key}={=Value}

当然可以直接循环Values:

{=Path}{=Name}


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

#dir指令
用于表示当前目录.
例如

#design指令
这个是一个block指令,用于插入设计时的代码,或者是注释 ,
例如


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

#comment指令
和#design用意一样, 不过这个不是block指令,不需要#end 例如


扩展的指令:

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


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


TemplateEngine的基本用法就介绍到这里了.
它还只是一个构造中的方案.
我也正在拿它来做一些小项目,积累一些经验,然后改进它.

 

你可能感兴趣的:(Web开发大全)