.NET Core中使用Razor模板引擎

來源:互聯網
上載者:User

標籤:

一、簡介

  在MVC以外的情境中,我們往往需要完成一些模板引擎產生代碼或頁面的工作;在以前我們一般常用的有Razor、NVeocity、VTemplate。雖然所有的模板系統都具有一些共同特徵,但 Razor卻和我們前面討論的二種視圖引擎截然不同。不同於其它視圖引擎,Razor在使用XML代 碼方面沒有走得那麼極端。它也不完全類似於ASPX,因為它把那些比較笨重的預留位置替換成@符號接運算式或者普通的控制塊。因為不需要特殊的結束標記,所 以Razor最終的代碼很簡練。

  本篇介紹的主角是Razor,在非Core的版本中,我們常用開源的RazorEngine來解決我們的問題;但是它卻沒有對應.NET Core的版本。我們也只要自己動手來完成一個支援.NET Core的“模板引擎”版本。

  一般情況下使用Razor作為視圖引擎要實現如下步驟:

  (1)讀模數板檔案 -> (2)產生Raozr的C#代碼 -> (3)使用Roslyn編譯代碼產生程式集 -> (4)動態載入程式集 -> (5)反射調用

  

二、非Mvc中使用Razor

  我們一般在使用Razor時都是在ASP.NET MVC中使用.cshtml來作為模板,由ASP.NET MVC的視圖引擎(ViewEngine)來產生頁面的代碼的,總之,這裡想說的是,模板引擎是獨立的,它們甚至是獨立的項目,由不同的公司和組織來開發。這次我們要在非Mvc中使用Raozr;首先我們要“脫離”Mvc的環境。

這裡我們只在.NET Core程式中引用微軟Raozr部分的程式集Microsoft.AspNetCore.Razor 1.0版本,這個程式集負責將模板產生出C#代碼。

1.Project.json添加引用
 "dependencies": {    "Microsoft.AspNetCore.Razor": "1.0.0"    "NETStandard.Library": "1.6.0"   }
2.模板產生代碼

  如下是摘錄的YOYOFx架構中的一段代碼,因為我們要產生代碼時一般需要傳入Model資料,這時需要Model Type組織代碼時,要將泛型的情況考慮進去 。這裡的RazorViewTemplate是一個模板基類,這裡包含了模板中調用的外部方法,我們常用到的如HtmlHelper、Render、Url、Raw等方法或類都是通過這個櫃頂模板定義的,RazorViewTemplate是一個自訂類不需要繼承其它類型,如果想擴充模板中使用的方法,只需要在這個類中加入即可。

    public class CodeGenerateService    {        public GeneratorResults Generate(Type modelType,string template)        {            //準備臨時類名,讀模數板檔案和Razor代碼產生器            string templateType = "YOYO.AspNetCore.ViewEngine.Razor.RazorViewTemplate";            string templateTypeName = modelType != null ? string.Format(templateType + @"<{0}>", modelType.FullName) : templateType;            var class_name = "c" + Guid.NewGuid().ToString("N");            var host = new RazorEngineHost(new CSharpRazorCodeLanguage(), () => new HtmlMarkupParser())            {                DefaultBaseClass = templateTypeName,                DefaultClassName = class_name,                DefaultNamespace = "YOYO.AspNetCore.ViewEngine.Razor",                GeneratedClassContext =                                   new GeneratedClassContext("Execute", "Write", "WriteLiteral", "WriteTo",                                                             "WriteLiteralTo",                                                             "RazorViewTemplate.Dynamic", new GeneratedTagHelperContext())            };            host.NamespaceImports.Add("System");            host.NamespaceImports.Add("System.Dynamic");            host.NamespaceImports.Add("System.Linq");            host.NamespaceImports.Add("System.Collections.Generic");            var engine = new RazorTemplateEngine(host);            return engine.GenerateCode(new StringReader(template));         }   }

  通過以上代碼得到GeneratorResults類型的結果,從而可以得知產生過程是否成功,錯誤在位置等資訊。最後通過GeneratedCode屬性,得到產生好的C#代碼。

    3.編譯模板

  一般Razor的C#代碼產生後,都是通過CodeDom來產生和編譯代碼的;.NET開源後,我們又多了一個強大的選擇Roslyn , Roslyn也是支援.NET Core的,並且在整個.NET平台中,扮演著非常重要的角色,小到這種視圖代碼編譯,大到整個項目的編譯情境都有Roslyn的身影。微軟最新開源的Visual Studio Code中C#外掛程式,OmniSharp就是通過Roslyn來對項目和編輯器提供支援的。

  摘錄YOYOFx代碼如下:

public Type Compile(string compilationContent){     var assemblyName = Path.GetRandomFileName();     var sourceText = SourceText.From(compilationContent, Encoding.UTF8);     var syntaxTree = CSharpSyntaxTree.ParseText( sourceText, path: assemblyName, options: new CSharpParseOptions());     var compilation = CSharpCompilation.Create(assemblyName, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),                        syntaxTrees: new[] { syntaxTree },                        references: ApplicationReferences );     using (var assemblyStream = new MemoryStream())
   { var result = compilation.Emit(assemblyStream, options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb)); this.CompileResult = new CompileResult(){ Success = result.Success, Errors = result.Diagnostics.Select(d => d.ToString()).ToList()}; if (!result.Success){ if (!compilation.References.Any() && !ApplicationReferences.Any()) throw new InvalidOperationException("project.json preserveCompilationContext"); return null; } var templateType = LoadTypeForAssemblyStream(assemblyStream, null); return templateType; }}

   在代碼中可以通過CompileResult得到相應的編譯錯誤資訊,同樣包括錯誤的資訊和具體錯誤所在的行。

  其中注意的是LoadTypeForAssemblyStream方法,因為在.NET Core中動態載入程式集的方式跟以前有所不同AppDomain的概念現在已經消失,所以要在.NET Core動態載入程式集要使用,命名空間System.Runtime.Loader中的AssemblyLoadContext.Default.LoadFromStream 方法,而在.NET 4.5+中要使用Assembly.Load方法。

 三、總結

   Razor 不僅僅使用了動態編譯,還有一個強大的模板解析的功能。利用自訂的模板基類還可以在模板裡提供一些輔助方法。這樣看來 Razor 也算是 C# DSL 的一種實現了。

 

 

  GitHubhttps://github.com/maxzhang1985/YOYOFx  如果覺還可以請Star下, 歡迎一起交流。

 

  .NET Core 和 YOYOFx 的交流群: 214741894  

 

  如果你覺得本文對你有協助,請點擊“推薦”,謝謝.

 

.NET Core中使用Razor模板引擎

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.