程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> Razor內幕之解析

Razor內幕之解析

編輯:關於ASP.NET

ASPX語法比較簡單,所以ASPX解析器幾乎完全是通過正則表達式來實現的。Razor解析器與ASPX解析器之間有很大不同,它實際上分為三個獨立的組件:

1)理解基礎HTML語法的標記解析器;

2)理解基礎C#或者VB語法的代碼解析器;

3)理解標記和代碼如何混合的中央控制器

所以Razor解析器有三個參與者:代碼解析器,標記解析器,代碼解析器。三個組件相互配合,協同工作完成對Razor文檔的解析。Razor解析器有三種狀態,分別是:解析標記文檔、解析標記塊,解析代碼塊,任何情況下解析器都處在以上三種狀態中的一種狀態上。前兩種狀態由標記解析器來處理,最後一種狀態由代碼解析器處理。

在此我們依然使用上次的例子來說明使用這些組件解析Razor文檔的過程。

文件內容如下:

<ul>
     @foreach(var p in Model.Products) {
     <li>@p.Name ([email protected])</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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved