最近剛好有要寫寄Email的程式,在代碼中寫HTML覺得很呆,抽出代碼外寫到txt或html檔當範本,由程式執行時在載入檔案時用Regex換關鍵字又覺得不夠好用,而且因為有時會有要判斷一些條件,就會寫一堆if esle在代碼中看了就討厭,因為寫MVC久了,就很希望範本也可以像MVC中的View,傳Model過去,在View層決定如何呈現,而更希望是使用Razor語法來寫範本,花了時間研究,找到RazorEngine,使用它來載入檔案,由它來編譯與執行並輸入結果。
RazorEngine
官網網址:http://razorengine.codeplex.com/
在找到RazorEngine之前曾經想過其他的方案,如T4與V8 Engine載jquery.template,但T4如果要獨立於MSBuild或Visual Studio執行有點麻煩,而V8 Engine我又不想在Class Library專案中放一堆js檔,後來就想到Razor,因為Razor的相關處理都是寫在System.Web.Razor,雖然Namespace叫System.Web,但根本沒有載入任何的System.Web相關的組件(如圖一),所以我肯定它可以獨立在非Web環境於中使用,在研究如何運用的期間,就發現早在去年就有人寫好放在CodePlex上,我太落伍了。
圖一 System.Web.Razor的參考,只有載入基本的三個組件
註:有興趣知道如何使用System.Web.Razor產生結果(基本上都是CodeDom),我所知道就有四套,小弟這一篇[ASP.NET MVC]Razor Views 預編譯(Pre-Compile)[1]-加快第一次執行回應速度介紹的二個Extension與本篇的RazorEngine與ASP.NET MVC 3使用的System.Web.WebPages.Razor,除了System.Web.WebPages.Razor外都是Open Source的可以下載Code來觀摩。
下面的範例,將展示如果只單獨使用System.Web.Razor.dll,如何產生結果(有點累,還是用別人的組件比較好)。
01 |
namespace RezorCodeDomSample |
03 |
internal class Program |
05 |
private static void Main( string [] args) |
08 |
string template = @"@{var name=""Would"";} |
11 |
var input = new System.IO.StringReader(template); |
13 |
//產生Razor的TemplateEngine |
14 |
var host = new RazorEngineHost( new CSharpRazorCodeLanguage()); |
15 |
host.DefaultBaseClass = "RezorCodeDomSample.MyTemplate" ; |
16 |
host.DefaultNamespace = "RezorCodeDomSample" ; |
17 |
host.DefaultClassName = "MyTemplateResult" ; |
18 |
var engine = new RazorTemplateEngine(host); |
21 |
var code = engine.GenerateCode(input); |
22 |
var codeType = code.GeneratedCode.Namespaces[0].Types[0]; |
23 |
var codeProvider = new CSharpCodeProvider(); |
26 |
//CodeGeneratorOptions options = new CodeGeneratorOptions(); |
27 |
//options.BlankLinesBetweenMembers = true; |
28 |
//System.IO.StringWriter sw = new System.IO.StringWriter(); |
29 |
//codeProvider.GenerateCodeFromCompileUnit(code.GeneratedCode, sw, options); |
30 |
//File.WriteAllText("c:\\text.cs", sw.ToString()); |
33 |
var options = new CompilerParameters() |
35 |
GenerateInMemory = true , |
36 |
GenerateExecutable = false , |
38 |
options.ReferencedAssemblies.Add( typeof (Program).Assembly.Location); |
39 |
var asselby = codeProvider.CompileAssemblyFromDom(options, code.GeneratedCode); |
42 |
var type = asselby.CompiledAssembly.GetType( "RezorCodeDomSample.MyTemplateResult" ); |
43 |
var ins = Activator.CreateInstance(type) as MyTemplate; |
45 |
Console.Write(ins.Reault); |
50 |
public class MyTemplate |
52 |
private StringBuilder sb = new StringBuilder(); |
54 |
public virtual void Execute() |
58 |
public void Write( object value) |
63 |
public void WriteLiteral( object value) |
70 |
get { return sb.ToString(); } |
使用範例(部份直接使用官網的範例)
一般用法
1 |
string template = "Hello @Model.Name! Welcome to Razor!" ; |
2 |
string result = Razor.Parse(template, new { Name = "World" }, "Sample" ); |
最後一個參數Name是選項參數,但建議給值因為關係到快取,如果有給,下次使用相同名稱的範本會用快取的,而且關係到範本的Include,雖然RazorEngine不能用RanderAction或RanderPartial但有提供Include可以載入,也是使用此Name為關鍵字。
使用.cshtml檔案
只要是副檔名為.cshtml,就算不在ASP.NET MVC3專案中,編輯.cshtml的方式都相同(但缺web.config中的設定,所以有些功能出不來),當然範本檔副檔名不一定要為.cshtml,但有IDE支援總比沒有好。
只是寫法要變,因為ASP.NET MVC 3的BaseType是System.Web.Mvc.WebViewPage,而RazorEngine的BaseType是RazorEngine.Templating.TemplateBase,除了Model屬性外其他的Html、Url、Ajax等等屬性都不沒有,但是C#的語法都支援。
1 |
string result = Razor.Parse(File.ReadAllText( "test.cshtml" ), new { IsVip = true , Name = "Wade" }); |
進階用法
Template的Include
RazorEngine雖然不支援RanderAction或RanderPartial,不過他有提供Include方法,載入已經Compile(或Parse)過的範本,以下是使用範例:
1 |
string template1 = "Hello @Model.Name" ; |
2 |
string template2 = "This is my sample template, @Include(\"Template1\",Model)" ; |
3 |
Razor.Compile(template1, "Template1" ); |
4 |
string result = Razor.Parse(template2, new { Name = "Wade" }); |
內嵌方法
如果只有單一個範本會用到的方法可以使用內嵌方法,以下是使用範例:
2 |
@helper MyMethod(string name) { |
6 |
@MyMethod(Model.Name)! Welcome to Razor!" ; |
8 |
string result = Razor.Parse(template, new { Name = "World" }); |
BaseType
每一個範本,最後都會使用System.Web.Razor.RazorTemplateEngine編譯成Class,而且繼承BaseType,所以BaseType決定了範本能使用的功能,如果還是不清楚以第一個範例為例:
1 |
@"@{var name=""Would"";} |
這些內容經剖析後會變成這樣
01 |
//與第一個範例拿掉註解後所產生的test.cs檔案相同 |
02 |
namespace RezorCodeDomSample |
04 |
public class MyTemplateRsult : RezorCodeDomSample.MyTemplate |
06 |
public MyTemplateRsult() |
10 |
public override void Execute() |
14 |
WriteLiteral( "Hello " ); |
18 |
WriteLiteral( "!!\r\n" ); |
這樣有比較清楚BaseType的功用了嗎?
所以如果希望所有的範本都可以使用的功能,可以繼承RazorEngine.Templating.TemplateBase,將擴充功能寫在子類別,然後註冊子類別,以下是使用範例:
01 |
public abstract class MyCustomTemplateBase<T> : TemplateBase<T> |
03 |
public string ToUpperCase( string name) |
05 |
return name.ToUpperCase(); |
10 |
Razor.SetTemplateBase( typeof (MyCustomTemplateBase<>)); |
12 |
string template = "My name in UPPER CASE is: @ToUpperCase(Model.Name)" ; |
13 |
string result = Razor.Parse(template, new { Name = "Matt" }); |
載入組件與命名空間
RazorEngine註冊CodeDom所使用的組件是使用AppDomain.CurrentDomain.GetAssemblies()的方式,所以只要在專案中所參考的組件,範本中都可以使用,還有為了增加撰寫的便利性,可以增加命名空間,以下是使用範例:
1 |
Razor.DefaultTemplateService.Namespaces.Add( "System.Xml" ); |
4 |
var xml = new XmlDocument(); |
8 |
string result = Razor.Parse< string >(template, "<Test>test</Test>" ); |
設定檔
跟ASP.NET MVC 3一樣,命名空間或BaseType等等都可以寫在設定檔中,詳情請參考官網
增加區段
1 |
<?xml version= "1.0" encoding= "UTF-8" ?> |
4 |
<section name= "razorEngine" type= "RazorEngine.Configuration.RazorEngineConfigurationSection, RazorEngine" requirePermission= "false" /> |
增加設定
01 |
<razorEngine activator= "RazorEngineSamples.Activators.MySampleActivator, RazorEngineSamples" |
02 |
factory= "RazorEngine.Web.WebCompilerServiceFactory, RazorEngine.Web" > |
04 |
<add namespace = "System.Linq" /> |
06 |
<templateServices default = "myCustomTemplateService" > |
07 |
<add name= "myCustomTemplateService1" language= "CSharp" /> |
08 |
<add name= "myCustomTemplateService2" templateBase= "MyTemplateBase" /> |
TemplateService可以讓某些範本使用不同的設定,以下是使用範例:
1 |
var service = Razor.Services[ "myCustomTemplateService" ]; |
2 |
string result = service.Parse( "Hello @Model.Name" , new { Name = "World" }); |
- 用Razor語法寫範本-RazorEngine組件介紹【转——非常好,可以用它来代替NVelocity】
RazorEngine 官網網址:http://razorengine.codeplex.com 在找到RazorEngine之前曾經想過其他的方案,如T4與V8 Engine載jquery.temp ...
- 開賣!下集 -- ASP.NET 4.5 專題實務(II)-範例應用與 4.5新功能【VB/C# 雙語法】
開賣!下集 -- ASP.NET 4.5 專題實務(II)-範例應用與 4.5新功能[VB/C# 雙語法] 我.....作者都沒拿到書呢! 全台灣最專業的電腦書店 -- 天瓏書局 已經開賣了! 感謝天 ...
- Java學習筆記(基本語法)
本文件是以學習筆記的概念為基礎,用於自我的複習紀錄,不過也開放各位的概念指證.畢竟學習過程中難免會出現觀念錯誤的問題.也感謝各位的觀念指證. 安裝JDK 在Oracle網站中找自己系統的JDK下載位置 ...
- vue起步和模板語法
vue構造器里有哪些內容: var a=new Vue({}) 模板語法: 文本插值: html: html的屬性里的值應該使用v-bind: 表達式: 指令; 參數:v-bind,v-on 雙向用戶 ...
- 查看LINQ Expression編譯後的SQL語法(转)
在用了LINQ語法之後的一個月,我幾乎把SQL語法全部拋到腦後了,不過 LINQ好用歸好用,但是實際上操作資料庫的還是SQL語法,如果不知道LINQ語法 編譯過後產生怎樣的SQL語法,一不小心效能就會 ...
- Delphi APP 開發入門(六)Object Pascal 語法初探
Delphi APP 開發入門(六)Object Pascal 語法初探 分享: Share on facebookShare on twitterShare on google_plusone_sh ...
- GO語言基礎教程:數組,切片,map
這節課我們來講解數組,切片和map,或許您是從其他語言轉到GO語言這邊的,那麼在其他語言的影響下您可能會不太適應GO語言的數組,因為GO語言把數組給拆分成了array,slice和map,接下來的時間 ...
- 何解決 LinqToExcel 發生「無法載入檔案或組件」問題何解決 LinqToExcel 發生「無法載入檔案或組件」問題
在自己的主機上透過 Visual Studio 2013 與 IISExpress 開發與測試都還正常,但只要部署到測試機或正式機,就是沒辦法順利執行,卡關許久之後找我協助.我發現錯誤訊息確實很「一般 ...
- jquery 語法
基本形式: $(selector).action() 文檔加載函數: $(document).Ready{ function(){ //將所有的函數寫到文檔加載函數里,可以防止頁面未加載完全,就執行j ...
随机推荐
- 008.KVM-VNC管理
一 VNC管理 1.1 修改配置 [root@kvm-host ~]# vi /etc/libvirt/qemu.conf …… vnc_listen = "0.0.0.0" 说明 ...
- Android通知栏沉浸式/透明化完整解决方案
转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6640649.html 参考文献:https://github.com/ljgsonx/adaptiveSt ...
- AWT事件模型
1.什么是事件 1)事件------描述发生了什么的对象 [事件与异常类似,是由一个个类构成的,当一个事件产生的时候,实际上是由对应的那个事件的类来生成了一个对象,这个对象封装了与这个事件相关的信息, ...
- 压缩归档文件审查工具p7zip-full
压缩归档文件审查工具p7zip-full 在数字取证中,会遇到各种形式的压缩文件和归档文件.为了处理这些不同的文件,Kali Linux提供了专用工具p7zip-full.该工具支持各种格式的压缩 ...
- [POI2013]Usuwanka
[POI2013]Usuwanka 题目大意: 一排\(n\)个球,有黑白两种颜色.每取走一个球会在原位置放一个水晶球.求构造一种取球方案,满足: 每次取走\(k\)个白球和\(1\)个黑球: 一次取 ...
- 《linux/unix设计思想》读后感
<linux/unix设计思想>这本书,觉得书的大部分内容都闲扯的太远了,以下简单的总结下本书的核心,帮助大家节省时间和金钱. linux/unix设计思想: 1) 程序应该小而专一,程序 ...
- 2010-2011 ACM-ICPC, NEERC, Moscow Subregional Contest Problem J. Joke 水题
Problem J. Joke 题目连接: http://codeforces.com/gym/100714 Description The problem is to cut the largest ...
- 基于ngx_lua的动态服务路由方案
基于ngx_lua的动态服务路由方案 http://geek.csdn.net/news/detail/131497
- MongoDB简单使用 —— 安装
下载 MongoDB的下载路径为:MongoDB Download Center.Win.Linux.Mac平台的都有,光Win平台的就提供msi和zip绿色版本的,这里我下载的是zip版本的. 命令 ...
- Modbus读写模拟量寄存器具体解释
读可读写模拟量寄存器: 发送命令(主机向从机)格式: [设备地址] [命令号03] [起始寄存器地址高8位] [低8位] [读取的寄存器数高8位] [低8位] [CRC校验的低8位] [CRC校验的高 ...