[译]Razor内幕之表达式

我们看一下之前例子中的代码:<li>@p.Name ($@p.Price)</li>是如何解析的。  当遇到"<li>"字符序列的时候,解析器知道正在解析一个以"</li>"为结束标志的标记。然后标记解析器在解析到结束标志之前发现了一个"@"字符,就像"@foreach"一样,再次切换到代码解析器。这时和之前的解析有些不同,C#代码解析器发现第一个标识符"p"时,它会检查这个标识符是不是C#的关键字;当然"p"并不是C#关键字,所以代码解析器进入"隐式表达式"模式。解析隐式表达式的算法看起来是这样的:

  1. 首先读取一个标识符,
  2. 下一个字符是"("或者"["?
    1. 是则读到匹配的")"或者"]",然后跳到2
    2. 不是则继续3
  3. 下一个字符是"."?
    1. 是则继续4
    2. 不是则结束表达式
  4. "."后面的字符是合法的C#标识符的开始?
    1. 是则读取"."并跳到1
    2. 不是则不读"."并结束表达式

总体来说就是:一个隐式表达式就是一个标识符,之后可以跟任意数量的方法调用("()")、索引表达式("[]")及成员访问表达式(".")。但是,除了在"()"或者"[]"里面,是不允许空格存在的。例如,下面是一些合法的Razor隐式表达式:

@p.Name  

@p.Name.ToString()  

@p.Name.ToString()[6 - 2]  

@p.Name.Replace("ASPX", "Razor")[i++]  

下面是一些非法的表达式,这些表达式只有部分("==>"之后的部分)会被Razor认为是表达式。

@1 + 1 ==> @  

@p++ ==> @p  

@p    .   Name ==> @p  

@p.Name.Length – 1 ==> @p.Name.Length  

这是我们为什么需要另一个表达式语法:"@(...)"的原因,通过这个语法我们可以把任何想要的东西放到"()"里面,上面的例子用这个语法来表示就是:

@(1 + 1)   

@(p++)   

@(p    .   Name)   

@(p.Name.Length - 1)  

一旦我们验证了表达式,我们会把它传递到代码生成器中。当为"@foreach () { … }"生成代码的时候,会把代码写到生成的C#类文件中。对于表达式(无论是显示的或者是隐式的)来说,这个过程有一点不同,不像ASPX,这里只有一个控制结构"@",并没有"@="来区分运行代码和要输出值的表达式,但这也是Razor的魅力所在。例如,当发现"@foreach"的时候,我们知道"foreach"是C#中的一个关键字,所以这个块会被作为声明来执行;而发现"@p.Name"或者"@(1 + 1)"的时候,我们知道它们是表达式,所以在执行这些语句之后输出了执行结果。

总之:

@if, @switch, @try, @foreach, @for, 等是和"<% %>"一样的

@p.Name, @(p++), @(1 + 1),等是和"<%: %>"一样的

另一个需要注意的地方就是表达式等同于"<%:"而不是"<%=""。在Razor中默认应该进行HTML Encode处理,如果不想进行HTML Encode处理,可以使用IHtmlString接口。

知道解析原理之后,下面我们再回到之前的代码:

<li>@p.Name ($@p.Price)</li>  

当发现"@p.Name"之后,可以识别出这是一个表达式,通过"("字符之前的空格解析出这不是一个方法调用,之后是文本标记""($",然后再次发现"@"之后将"@p.Price"解析为表达式,最后以")"结束。

 

查看下一篇:Razor内幕之模板

查看原文,点击此处

注:如果发现有翻译不恰当或者疏漏的地方请反馈给我,我会及时更正,谢谢!

posted @ 2010-08-18 15:31  镜涛  阅读(1526)  评论(2编辑  收藏  举报
Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名孙镜涛(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言