理解模板引擎Razor 的原理
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>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
以空格或是@作为区域(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");
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
编译标记文件生成的类型,生成Code Dom 脚本
CompilerResults compilerResults =
new CSharpCodeProvider()
.CompileAssemblyFromDom(
new CompilerParameters(/*...*/),
razorResult.GeneratedCode
);
执行生成的程序集类型,获取结果
var template = (CustomTemplateBase)Activator.CreateInstance(“ProgrammingRazor.DemoTemplate”);
template.Execute();
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Razor Pad程序的功能,也是用的这个基本思路来展来的。
Razor Pad是一个开放源码的程序,你可以从网址http://razorpad.codeplex.com中获取它的源代码。
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
理解模板引擎Razor 的原理的更多相关文章
- 理解模板引擎Razor 的原理(转载)
Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项.简洁的语法与.NET Framework 结合,广泛应用于ASP.NET MVC 项目.Razor Pad是一 ...
- 【转链接】Handlebars模板引擎以及浅谈模板引擎的实现原理
什么叫做“模板引擎“?我是这么理解的:就是对一些待填入数据的占位符的解析.如果你使用过Python的django框架,那你肯定是模板一点也不陌生.模板引擎就是解析模板的,把后端数据塞到前端页面模板. ...
- [2018-08-25]模板引擎Razor Engine 用法示例
好久没写博客了,回宁波后最近几个月一直忙些线下的事情. 敲代码方面脱产有阵子了,生疏了,回头一看,这行业果然更新飞快. 最近线下的事情基本忙完,准备开始干回老本行,最重要的一件事就是升级abplus库 ...
- doT.js模板引擎及基础原理
时至今日,基于后端JavaScript(Node.js)和MVC思想也开始流行起来.模板引擎是数据和页面分离工作中最重要的一环,在各大门户网站均有利用到模板引擎. 模板引擎有很多种,但是原理了解也是非 ...
- 模板引擎的简单原理template
var templateStr = "我的名字叫<%=name%>我是一只小狗,今年<%=age%>岁."; var data = { name:'旺财 ...
- (转)浅谈dedecms模板引擎工作原理及自定义标签
理解织梦模板引擎有什么意义?一方面可以更好地自定义标签.更多在于了解织梦系统,理解模板引擎是理解织梦工作原理的第一步.理解织梦会使我们写php代码时更顺手,同时能学习一些php代码的组织方式. 这似乎 ...
- 浅谈dedecms模板引擎工作原理及其自定义标签
浅谈dedecms模板引擎工作原理: 理解织梦模板引擎有什么意思? 可以更好地自定义标签.更多在于了解织梦系统,理解模板引擎是理解织梦工作原理的第一步. 理解织梦会使我们写PHP代码是更顺手,同时能学 ...
- PHP的模板引擎smarty原理是什么(整理)
PHP的模板引擎smarty原理是什么(整理) 一.总结 一句话总结:其实所有的模板引擎的工作原理是差不多的,无非就是在php程序里面用正则匹配将模板里面的标签替换为php代码从而将两者混合为一个ph ...
- JavaScript模板引擎原理,几行代码的事儿
一.前言 什么是模板引擎,说的简单点,就是一个字符串中有几个变量待定.比如: var tpl = 'Hei, my name is <%name%>, and I\'m <%age% ...
随机推荐
- lazy?
https://developer.jboss.org/wiki/LazyEJB31timerservicedeploymentstartingJBossAS600M5 2016-09-28 18:5 ...
- unity3d多线程坑
单独起了一个线程来处理网络相关操作,比较常规的做法.本身没啥特别的东西,碰到了一个不大不小的坑折腾了好久,记录下来吧. 简单的说就是子线程中抛出的异常,如果没有catch的话,会导致子线程悄无声息的退 ...
- devise 小项目(一)
Devise源于Warden,而warden是一个基于Rack的验证权限gem,不过,使用devise实际并不需要任何关于warden的知识. 如果你之前有一些其他类似的维护验证权限功能的gem的使用 ...
- 使用小技巧,让你高效使用Eclipse
1.自动完成--Eclipse有一个自动完成代码功能,快捷键是ctrl + space.当点击时就会弹出一个对话框,上面有与前后文相关的一些建议.只要有一个可能性,Eclipse就会替你完成. 2.快 ...
- Individual Project - Word frequency program - Multi Thread And Optimization
作业说明详见:http://www.cnblogs.com/jiel/p/3978727.html 一.开始写代码前的规划: 1.尝试用C#来写,之前没有学过C#,所以打算先花1天的时间学习C# 2. ...
- eclipse中输入中文为繁体
http://blog.163.com/guomaolin_gavin/blog/static/199618307201218104452930/ eclipse中输入中文为繁体! 2012-02-0 ...
- 如何判断ScrollView滑动方形
1/判断滚动视图左右滚动 { CGFloat startContentOffsetX;//滚动开始的坐标 CGFloat willEndContentOffsetX; //滚动即将停止的坐标 CGFl ...
- 浅论Android网络请求库——android-async-http
在iOS开发中有大名鼎鼎的ASIHttpRequest库,用来处理网络请求操作,今天要介绍的是一个在Android上同样强大的网络请求库android-async-http,目前非常火的应用Insta ...
- MVC中调用Public_Class时,VS2012老提示:当前上下文中不存在名称“Json”的解决方法
TMD,老TMD困扰我,每次新建MVC项目后就提示这个,原因在此: public class Public_Class <==此处应为:Public_Class : Controller { ...
- .net与mono的那些事
米格尔·德伊卡萨在.NET的文档于2000年10月发布时就马上对.NET产生了兴趣.在查看字节码解释器后,他发现对于元数据(metadata)没有相应的说明文档.2001年2月,德伊卡萨在.NET邮件 ...