【搬運外國同行文章】在非網頁程式裡使用razor模板引擎
阿新 • • 發佈:2019-01-25
【前言】近日研究程式碼生成,急需一個模板引擎,找到了一篇外國同行的文章,裡面有如何在其他環境裡面使用razor而且詳細說明了原理,非常好,本人雖然英語戰力<=5,但是也勉強看得懂,ok,原文地址如下:
下面是本人的渣翻,如有錯漏,請指正,謝謝。
如何在非網頁程式裡使用razor模板引擎?
微軟最近推出了razor模板引擎技術,雖然該技術與asp.net mvc 預覽版捆綁在一起,但是它可以應用於非asp.net程式裡面。 Razor是asp.net webform外的另一種模板技術,它可以代替目前廣泛應用在webform和mvc上面的aspx模板技術。 【我就不逐句逐句翻譯了,如何使用的翻譯如下:】 假如你還沒有下載這個專案的話,請返回原網址下載,或者點選這裡下載:開始
@inherits RazorHosting.RazorTemplateBase @using System.Reflection Hello @Context.FirstName! Your entry was entered on: @Context.Entered @{ // Code block: Update the host Windows Form passed in through the context Context.WinForm.Text = "Hello World from Razor at " + DateTime.Now.ToString(); } AppDomain Id: @AppDomain.CurrentDomain.FriendlyName Assembly: @Assembly.GetExecutingAssembly().FullName Code based output: @{ // Write output with Response object from code string output = string.Empty; for (int i = 0; i < 10; i++) { output += i.ToString() + " "; } Response.Write(output); }
@inherits RazorHosting.RazorTemplateBase備註:上面 的 inheribts將預設的模板型別改寫成為 RazorTemplateBase,它並非必須的,但是它最大的好處在於,能夠讓 vs 提供這個模板型別的智慧提示,何樂而不為? 上面是模板的內容,下面將介紹如何解析這個模板:
var engine = new RazorEngine<RazorTemplateBase>(); // we can pass any object as context - here create a custom context var context = new CustomContext() { WinForm = this, FirstName = "Rick", Entered = DateTime.Now.AddDays(-10) }; string output = engine.RenderTemplate(this.txtSource.Text new string[] { "System.Windows.Forms.dll" }, context); if (output == null) this.txtResult.Text = "*** ERROR:\r\n" + engine.ErrorMessage; else this.txtResult.Text = output;
這是最簡單最快捷的方式,其中 CustomContext是作者(譯者注:作者為 Rick Strahl)新增的一個上下文變數,用來傳遞到模板裡面,在模板裡面可以這樣呼叫context的引數:
@Context.FirstName
值得提醒的是,並非所有物件都可以放進context裡面,只有可序列化的物件才可以(假如包含有方法的物件,那麼就不行了),否則會報錯。
假如你不想將字串傳進來而直接用檔案流來解析模板,那麼可以這樣用:
using (reader = new StreamReader("templates\\simple.csHtml", true)) { result = host.RenderTemplate(reader, new string[] { "System.Windows.Forms.dll" }, this.CustomContext); }
上面解析模板的api都是RenderTemplate,這個是封裝好的高階用法,假如您希望更加精確控制模板的分析行為,那麼可以使用較底層的api,例如:
// we can pass any object as context - here create a custom context var context = new CustomContext() { WinForm = this, FirstName = "Rick", Entered = DateTime.Now.AddDays(-10) }; var engine = new RazorEngine<RazorTemplateBase>(); string assId = null; using (StringReader reader = new StringReader(this.txtSource.Text)) { assId = engine.ParseAndCompileTemplate(new string[] { "System.Windows.Forms.dll" }, reader); } string output = engine.RenderTemplateFromAssembly(assId, context); if (output == null) this.txtResult.Text = "*** ERROR:\r\n" + engine.ErrorMessage; else this.txtResult.Text = output;
注意:翻譯到這裡我就明白如何用這個東西了,假如你要呼叫自己的dll,譬如:Mytools.Common類庫,那麼就必須在解析模板的時候宣告該dll,譬如:
result = host.RenderTemplate(reader, new string[] { "System.Windows.Forms.dll","Mytools.Common.dll" }, this.CustomContext);
接下來的都是一些高階用法,各位有興趣可以去原網址查閱。
備註:如何在vs裡面獲得程式碼提示功能?任意類庫的提示。
這裡以vs2010為例,其中: 這位兄弟幫了大忙。 首先,在專案下面新增一個web.config 裡面內容如下:<?xml version="1.0" encoding="utf-8"?>
<!--
有關如何配置 ASP.NET 應用程式的詳細資訊,請訪問
http://go.microsoft.com/fwlink/?
LinkId=169433
-->
<configuration>
<configSections>
</configSections>
<connectionStrings>
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<compilation debug="true">
<assemblies>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</assemblies>
<!--
<buildProviders>
<add extension=".cshtml"
type="Microsoft.WebPages.Compilation.InlinePageBuildProvider" />
</buildProviders>
-->
</compilation>
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
<add namespace="Easis.Common"/>
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule"
scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64"
responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
有了這個東西,以後在這個專案下面新建的任何cshtml文件都會有智慧程式碼提示功能,但是對於第三方類庫是沒有提示的,如何解決? 請看:
<compilation debug="true">
<assemblies>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add assembly="RazorHosting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
<add assembly="Easis.Common,Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
<add assembly="Easis.Security, Version=1.0.0.0, Culture=neutral,PublicKeyToken=null"/>
</assemblies>
在assemblies標籤下面新增第三方類庫,然後將第三方的dll都放到bin目錄。。注意:沒有bin目錄的要新建一個,並且不能放在bin/debug或者bin/release下面,因為web config匯入去的路徑就是bin,你可以在 專案的生成裡面設定輸出路徑為: bin/ ok,做完這些你應該可以看到完美的程式碼提示功能了, 請注意,使用這個razorHosting的時候要請順便將dll導進去,否則會報錯。 下面再分享一個小工具,這個小工具的作用是分析dll檔案,獲得具體的引用資訊,免得大家不知道version,publicktoken之類的資訊 無法新增到web config裡面。