文章出處

Razor Engine,之前僅僅是ASP.NET MVC的一種View引擎,目前已經完全成為一種可以獨立使用的模版引擎,并且已經成為了CodePlex上一個開源的項目(http://razorengine.codeplex.com/)。對于使用過ASP.NET MVC Razor視圖引擎的朋友們一定已經領略過它的靈活性和易用性,在這篇文章中我們將利用它來實現一個代碼生成器使我們可以以Razor的語法來定義代碼模版。[源代碼從這里下載]

在《一個簡易版的T4代碼生成"框架"》這篇文章中,我創建了一個能夠生成多個文件的代碼生成器,其核心是兩個基本的類型:Template類生成代碼文件的內容,Generator執行Template。現在我將通過自定義一個基于Razor Engine的Template,讓它讀取以Razor語法編寫的模版文件并生成相應的代碼。

不過在具體介紹實現原理之前,還是先來看看它能夠達到的效果。如右圖所示,我們還是通過一個.tt文件(Generator.tt)來生成相應的代碼文件,具體生成的代碼文件就是依賴于該.tt文件的三個.cs 文件:Foo.cs、Bar.cs和Baz.cs。簡單起見,我們僅僅在這三個文件中生成了一個與文件同名的空Class,它們的定義如下。

   1: public class Foo
   2: {
   3: }
   4:  
   5: public class Bar
   6: {
   7: }
   8:  
   9: public class Baz
  10: {
  11: }

如下所示的是Generator.tt的內容,它直接執行一個類型為DemoGenerator的生成器。

   1: <#@ template hostspecific="true" language="C#" #>
   2: <#@ assembly name="$(TargetDir)Artech.CodeGeneration.dll" #>
   3: <#@ import namespace="Artech.CodeGeneration" #>
   4: <#@ output extension=".empty" #>
   5: <#this.RunCodeGenerator(this.Host, new DemoGenerator());#>

作為代碼生成器的DemoGenerator定義如下,它重寫了CreateTemplates方法并返回一個包含三個RazorTemplate<TModel>的字典,該字典的Key表示生成的文件名。

   1: public class DemoGenerator: Generator
   2: {
   3:     protected override IDictionary<string, Template> CreateTemplates()
   4:     {
   5:         Dictionary<string, Template> templates = new Dictionary<string, Template>();
   6:         templates.Add("Foo.cs", new RazorTemplate<string>("template.razor", "Foo"));
   7:         templates.Add("Bar.cs", new RazorTemplate<string>("template.razor", "Bar"));
   8:         templates.Add("Baz.cs", new RazorTemplate<string>("template.razor", "Baz"));
   9:         return templates;
  10:     }
  11: }

構建RazorTemplate<TModel>需要傳入兩個參數,第一個參數是用于定義Razor模版的文件路徑(可以是絕對路徑,也可以是相對于.tt文件的相對路徑),另一個是作為Model的對象(相當于ASP.NET強類型View的Model)。通過上面的代碼可以看出,三個RazorTemplate<TModel>均使用同一個Model類型為字符串的模版文件template.razor,該模版內容定義如下。可以看出作為Model的字符串在模版中作為了生成類型的名稱。

   1: public class @Model
   2: {
   3: }

我假設你已經了解了《一個簡易版的T4代碼生成"框架"》這篇文章的內容,所以我們只需要簡單介紹RazorTemplate<TModel>的定義就可以了。首選RazorTemplate<TModel>是一個具有如下定義的RazorTemplate類型的子類。RazorTemplate的只讀屬性TemplateFileName 表示Razor模版的路徑,用于讀取模版文本內容的虛方法GetTemplateText直接讀取指定模版文件的內容。在重寫的TransformText方法中,我們調用Razor的靜態方法Parse對模版內容進行解析并生成代碼文本。

   1: public class RazorTemplate : Template
   2: {
   3:     public string TemplateFileName { get; private set; }
   4:     public RazorTemplate(string templateFileName)
   5:     {
   6:         this.TemplateFileName = templateFileName;
   7:     }
   8:     protected virtual string GetTemplateText()
   9:     {
  10:         string path = this.TemplateFileName;
  11:         if (!Path.IsPathRooted(path))
  12:         {
  13:             path = Path.Combine(Path.GetDirectoryName(TransformContext.Current.Host.TemplateFile), path);
  14:         }
  15:         return File.ReadAllText(path);
  16:     }
  17:  
  18:     public override string TransformText()
  19:     {
  20:         return Razor.Parse(this.GetTemplateText());
  21:     }
  22: }

繼承自RazorTemplate的泛型RazorTemplate<TModel>定義如下。它具有一個表示Model的只讀屬性,該屬性在構造函數中被初始化。在重寫的TransformText方法中,我們調用Razor泛型的靜態方法Parse<TModel>解析模版文本并傳入Model對象。

   1: public class RazorTemplate<TModel> : RazorTemplate
   2: {
   3:     public TModel Model { get; private set; }
   4:     public RazorTemplate(string templateFileName, TModel model)
   5:         : base(templateFileName)
   6:     {
   7:         this.Model = model;
   8:     }
   9:  
  10:     public override string TransformText()
  11:     {
  12:         return Razor.Parse<TModel>(this.GetTemplateText(), this.Model);
  13:     }
  14: }

 

相關閱讀:
與VS集成的若干種代碼生成解決方案[博文匯總(共8篇)]
通過CodeDOM定義生成代碼的結構
通過Visual Studio的Custom Tool定義代碼生成器
不同于CodeDOM的代碼生成機制——T4
通過T4模板實現單文件的代碼生成
通過T4模板實現多文件的代碼生成
解決T4模板的程序集引用的五種方案
編寫T4模板進行代碼生成無法避免的兩個話題:"Assembly Locking"&"Debug"
通過自定義BuildProvider為ASP.NET提供代碼生成


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()