Razor是ASP.NET MVC 3中新加入的技術,以作為ASPX引擎的一個新的替代項。簡潔的語法與.NET Framework 結合,廣泛應用於ASP.NET MVC 專案。Razor Pad是一個編輯Razor指令碼的工具,脫離於ASP.NET 和Visual Studio。

微軟已經有一套模板引擎T4,在設計ASP.NET MVC 3時又設計一套模板引擎Razor,對開發者而言是多一種選擇,但同時也增加學習成本,至今我都沒有時間和精力將Code Smith的模板轉化為T4的模板。

Razor  從模板到.NET 程式碼

以cshtml為字尾名的為Razor模板,可以混合指令碼語言和Html程式碼,以呈現為ASP.NET Page頁面。

來看下面的Razor指令碼片段,它以div的格式輸出Posts物件的標題:

<div>
@foreach(var post in Posts) {
<div>@post.Title</div>
}
</div>

Razor引擎分析上面的指令碼,產生如下所示的Xml文字片段

<Document>
<Markup><div>\r\n\t</Markup>
<Statement>
<Transition>@</Transition>
<Code>foreach(var post in posts) { </Code>
<Markup>
<Markup><div></Markup>
<Expression>
<Transition>@</Transition>
<ImplicitExpression>post.Title</ImplicitExpression>
</Expression>
<Markup></div></Markup>
</Markup>
<Code> } </Code>
<Markup></div></Markup>
</Statement>
<Markup>\r\n</div></Markup>
</Document>

以空格或是@作為區域(block)的分割符,將Razor解析成一個表示式樹。@在Razor模板中的用法相當靈活,可以用於表示式的求值,或是定義程式碼塊。

然後產生.NET程式碼,上面的指令碼,會產生如下的.NET程式碼型別

namespace Razor {
public class __CompiledTemplate {
public __CompiledTemplate() {
}
public override void Execute() {
WriteLiteral("<div>\r\n\t");
@foreach(var post in posts) {
WriteLiteral("<div>");
Write(post.Title);
WriteLiteral("</div>");
}
WriteLiteral("\r\n</div>");
}
}
}
 

最後,應用CodeDom API編譯上面的程式碼,呼叫Execute方法輸出結果。

Razor API

一開始接觸這項技術時,以為是ASP.NET MVC的一個開源專案,接觸之後才知道它是.NET Framework API中的型別,幾年沒有做Web開發,ASP.NET技術發展的確實很快。

System.Web.Razor.Parser.RazorParser

RazorParser用於解析指令碼,但是它對Html,CS,VB指令碼一無所知。MarkupParser用於解析Html標記,CSharpCodeParser用於解析包含C#程式碼的標記,相應的VBCodeParser則用於解析包含VB指令碼的標記,

System.Web.Razor.Generator.RazorCodeGenerator

根據傳入的Markup Parser,產生程式碼。與Parser相似,它也有二個與標記語言相關的型別,CSharpRazorCodeGenerator 和VBRazorCodeGenerator,用於處理標記包含的指令碼。

System.Web.Razor.RazorEngineHost

System.Web.Razor.RazorTemplateEngine

引擎宿主,用於接受標記指令碼,產生.NET 型別的程式碼。

把上面的內容綜合起來,寫一個例子程式,來看這些API的用法。

建立指令碼宿主

var language = new CSharpRazorCodeLanguage();
var host = new RazorEngineHost(language) {
DefaultBaseClass = "CustomTemplateBase",
DefaultClassName = "DemoTemplate",
DefaultNamespace = "ProgrammingRazor",
};
 

新增Razor指令碼引擎,讀取標記(Markup)檔案

RazorTemplateEngine engine = new RazorTemplateEngine(host);
GeneratorResults razorResult = engine.GenerateCode("C:\\Script.txt");

編譯標記檔案生成的型別,生成Code Dom 指令碼

CompilerResults compilerResults =
new CSharpCodeProvider()
.CompileAssemblyFromDom(
new CompilerParameters(/*...*/),
razorResult.GeneratedCode
);

執行生成的程式集型別,獲取結果

var template = (CustomTemplateBase)Activator.CreateInstance(“ProgrammingRazor.DemoTemplate”);
template.Execute();
 

Razor Pad程式的功能,也是用的這個基本思路來展來的。

Razor Pad是一個開放原始碼的程式,你可以從網址http://razorpad.codeplex.com中獲取它的原始碼。