ASPX语法比较简单,所以ASPX解析器几乎完全是通过正则表达式来实现的。Razor解析器与ASPX解析器之间有很大不同,它实际上分为三个独立的组件:

  1)理解基础HTML语法的标记解析器;

  2)理解基础C#或者VB语法的代码解析器;

  3)理解标记和代码如何混合的中央控制器

  所以Razor解析器有三个参与者:代码解析器,标记解析器,代码解析器。三个组件相互配合,协同工作完成对Razor文档的解析。Razor解析器有三种状态,分别是:解析标记文档、解析标记块,解析代码块,任何情况下解析器都处在以上三种状态中的一种状态上。前两种状态由标记解析器来处理,最后一种状态由代码解析器处理。

  在此我们依然使用上次的例子来说明使用这些组件解析Razor文档的过程。

  文件内容如下:

<ul>   
    @foreach(var p in Model.Products) {   
    <li>@p.Name ($@p.Price)</li>   
    }   
</ul>   

  我们从最上面开始解析过程。当第一次调用核心解析器的时候,它会调用标记解析器来解析标记文档。此时,解析器处在解析标记文档状态,在这种状态下,它会一直向前扫描,直到找到下一个"@"字符,除此之外它不关心任何标记或者其它HTML相关的内容。当遇到一个"@"字符的时候,它会通过查看"@"字符前后的内容,并据此判断是切换到代码状态呢还是这仅仅是一个email地址。这是默认的处理方式,但是有些特殊情况会强制解析器切换到代码解析状态。本例中,当解析到"@"字符的时候,会发现该字符的前面是空格,据此判定这并不是一个合法的email地址,所以切换到代码解析状态。

  标记解析器接着调用代码解析器,让其来解析代码块。在Razor中块为单独的一段代码或者是有明确开始结束字符序列的标记,因而此处的"foreach"声明是代码块,它以字符"f"开始,以字符"}"结束。代码解析器非常清楚C#语法,他会跟踪C#指令,当遇到"<li>"字符序列的时候,它知道此处应该是C#指令的开始,但C#并不支持这样的指令,因而代码解析器会再次调用标记解析器来解析接下来的HTML代码块。这样在代码和标记解析器之间创建一种从标记解析开始,进入代码解析,然后再进入标记解析….的递归过程。到目前为止,解析器内的调用栈应该类似于以下结构(省略了一些帮助方法):

HtmlMarkupParser.ParseDocument() 
CSharpCodeParser.ParseBlock() 
HtmlMarkupParser.ParseBlock() 

  我们可以从中看出ASPX和Razor的区别:在ASPX文件中,代码和标记可以看作是两个并行的流,我们写一些标记然后跳过去写一些代码,再跳回来写标记,如此进行;而Razor文件更像是一棵树,我们写一些标记,然后在标记里面写一些代码,再在代码中嵌入标记….。

  所以我们仅需要调用标记解析器去解析"<li>"和"</li>"之间的标记块,在没有到达"</li>"之前解析器认为标记块还没结束,哪怕在标记之间有"}"字符都不会打断"foreach"声明。

  当解析"<li>"的时候,标记解析器发现了"@"字符,因而代码解析器会被调用,此时栈结构变成:

HtmlMarkupParser.ParseDocument() 
CSharpCodeParser.ParseBlock() 
HtmlMarkupParser.ParseBlock() 
CSharpCodeParser.ParseBlock() 

  对于这些代码块如何终止的具体信息以后再做介绍,但是最终我们会完成这些代码块的解析并且回到"<li>"块中,在"</li>"之后又回到了"foreach"块中,最后"}"字符结束了"foreach"块,重新回到栈的顶端:标记文档。之后因为没发现新的"@"字符,文档解析器将一直解析到文件的结尾。

  查看英文原文http://blog.andrewnurse.net/CommentView,guid,8bfec649-9b91-4f0f-b051-555cea414720.aspx

Razor内幕之解析的更多相关文章

  1. Spring技术内幕——深入解析Spring架构与设计原理(一)IOC实现原理

    IOC的基础 下面我们从IOC/AOP开始,它们是Spring平台实现的核心部分:虽然,我们一开始大多只是在这个层面上,做一些配置和外部特性的使用工作,但对这两个核心模块工作原理和运作机制的理解,对深 ...

  2. Struts2技术内幕----深入解析Struts2架构与设计(一)

    Struts2的核心入口程序,从功能上来说必须能够处理Http请求,这是表示层框架的基本要求.为了达到这一目的,Struts2毫无例外地遵循了Servlet标准,通过实现标准的Filter接口来进行H ...

  3. jQuery技术内幕 深入解析jQuery架构设计与实现原理

    jquery的外衣 jquery是一个轻量级的JS框架 //以下截取自jquery源码片段 (function( window, undefined ) { /* 源码内容 */ })( window ...

  4. Razor 视图引擎 – ASP.NET MVC 4 系列

           Razor 视图引擎是 ASP.NET MVC 3 开始扩展的内容,并且也是默认视图引擎.        Razor 通过理解标记的结构来实现代码和标记之间尽可能顺畅的转换.下面的例子演 ...

  5. HDFS追本溯源:HDFS操作的逻辑流程与源码解析

    本文主要介绍5个典型的HDFS流程,这些流程充分体现了HDFS实体间IPC接口和stream接口之间的配合. 1. Client和NN Client到NN有大量的元数据操作,比如修改文件名,在给定目录 ...

  6. Struts2技术内幕 读书笔记一 框架的本质

    本读书笔记系列,主要针对陆舟所著<<Struts2技术内幕 深入解析Strtus2架构设计与实现原理>>一书.笔记中所用的图片若无特殊说明,就都取自书中,特此声明. 什么是框架 ...

  7. 【初探Spring】------Spring IOC(三):初始化过程---Resource定位

    我们知道Spring的IoC起到了一个容器的作用,其中装得都是各种各样的Bean.同时在我们刚刚开始学习Spring的时候都是通过xml文件来定义Bean,Spring会某种方式加载这些xml文件,然 ...

  8. ASP.NET MVC 从零开始 - create and run

    这篇文章是从我的 github 博客 http://lxconan.github.io 导入的. 如果你想用 ASP.NET MVC 创建一个网络应用,那么你可以搜到很多的文章.但是没有多少文章告诉你 ...

  9. iteye上总结的编程精华资源

    原文:http://www.iteye.com/magazines/130 博客是记录学习历程.分享经验的最佳平台,多年以来,各路技术大牛在ITeye网站上产生了大量优质的技术文章,并将系列文章集结成 ...

随机推荐

  1. egg 使用手记(一)

    1. 文件加载规则 引用官方的说法: 框架在加载文件时会进行转换,因为文件命名风格和 API 风格存在差异.我们推荐文件使用下划线,而 API 使用驼峰.比如 app/service/user_inf ...

  2. FastAdmin + uni-app

    FastAdmin + uni-app FastAdmin https://www.FastAdmin.net uni-app http://uniapp.dcloud.io/ 自己先挖个坑.

  3. 6kzz整合ueditor

    用过6kzz免费版的朋友都知道,它的后台编辑器是kindeditor,并且是两三年前的版本,有很多功能都没有,现在的kindeditor也不错,但感觉还是没有百度的ueditor强大(据说微信后台的编 ...

  4. (转)VS2008 VMware联合调试

    本文转载自:http://www.cnblogs.com/ziwuge/archive/2012/04/03/2431162.html 一.前期准备: 1. 安装VS2008 2. 安装VM8.0,在 ...

  5. 如何用FFmpeg API采集摄像头视频和麦克风音频,并实现录制文件的功能

    之前一直用Directshow技术采集摄像头数据,但是觉得涉及的细节比较多,要开发者比较了解Directshow的框架知识,学习起来有一点点难度.最近发现很多人问怎么用FFmpeg采集摄像头图像,事实 ...

  6. Windows修改MySQL用户root密码

    MySQL是一个关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软 ...

  7. hadoop中unhealthynodes的问题解决

    在yarn-site.xml中加入如下配置 <property>     <name>yarn.nodemanager.disk-health-checker.min-heal ...

  8. spring mvc default-servlet mvc:resources mvc:default-servlet-handler区别

    mvc:default-servlet-handler其实就是default-servlet 交由web容器自己处理 mvc:resources spring来处理 没有被映射的url web容器来处 ...

  9. EOFException异常的处理

    TOmcat启动后报:IOException while loading persisted sessions: Java.io.EOFException错误 - IOException while ...

  10. Jquery缩放

    $(document).mousemove(function(e) {     if (!!this.move) {         var posix = !document.move_target ...