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提供代码生成

Razor Engine,实现代码生成器的又一件利器的更多相关文章

  1. [2018-08-25]模板引擎Razor Engine 用法示例

    好久没写博客了,回宁波后最近几个月一直忙些线下的事情. 敲代码方面脱产有阵子了,生疏了,回头一看,这行业果然更新飞快. 最近线下的事情基本忙完,准备开始干回老本行,最重要的一件事就是升级abplus库 ...

  2. Terminologies in MVC: Part 2 (Razor Engine Syntax vs Web Form)

    By Abhishek Jaiswal :) on Mar 21, 2015 In this article we learn about Razor Engine Syntax vs Web For ...

  3. VS2010下WPF开发ARCGIS ENGINE 10的带Ribbon控件项目

    原文 http://blog.sina.com.cn/s/blog_47522f7f0100nq5t.html 题目好长,但是集目前最新的工具于一身..VS是最新的2010版,不过用的是.net3.5 ...

  4. Razor Engine,动态脚本语言,mvc上的语法,适用于文件内容生成,静态网页生成等。

    https://razorengine.codeplex.com/ 下载并引用:razorengine.dll 代码里这样写,用mvc的人都会!Razor语法! string template = & ...

  5. Razor - 模板引擎 / 代码生成 - RazorEngine

    目录 Brief Authors Official Website RazorEngine 的原理 - 官方解释 安装记录 Supported Syntax (默认实现支持的语法) 测试记录 - ca ...

  6. asp.net mvc简单实现基于Razor的分页控件

    最近在写一些web应用了解了一下asp.net mvc发现的确好用,所以直接就干上了.不过在使用asp.net mvc的Razor模板的情况并不向传统webform那样可以使用控件.但从Razor的功 ...

  7. A Look at the Razor View Engine in ASP.NET MVC

    The biggest architectural difference that exists between ASP.NET MVC and ASP.NET Web Forms is the ne ...

  8. mvc 4 Razor (@html.xx)语法大全以及应用

    Razor语法大全  @Html ASP.NET MVC 中@Html.Partial,@Html.Action,@Html.RenderPartial,@Html.RenderAction差别 对这 ...

  9. FreeSql.Generator命令行代码生成器是如何实现的

    目录 FreeSql介绍 FreeSql.Generator RazorEngine.NetCore 源码解析 FreeSql.Tools FreeSql FreeSql 是功能强大的对象关系映射技术 ...

随机推荐

  1. myeclipse中source not found问题解决办法

    myeclipse中出现source not found是因为你所引用的JavaEE Generic Library没有关联源码,如下图: 下面给出该问题的解决办法: 步骤一:去下载apache-to ...

  2. ST

    这次说一下测试的基础部分 软件测试 软件测试(英语:software testing),描述一种用来促进鉴定软件的正确性.完整性.安全性和质量的过程.换句话说,软件测试是一种实际输出与预期输出间的审核 ...

  3. javascript array sort()

    [5,10,1].sort(); 结果[1,10,5] 有点出人意料. array.sort( sortFunction )可选-指定如何比较元素顺序的函数名称 如果省略sortFunction参数, ...

  4. 个人查阅资料-Sql语句

    SQL分类: DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE) DML—数据操纵语言(SELECT,DELETE,UPDATE,INSERT) DCL—数据控制语言(GRAN ...

  5. 享元模式 - Flyweight

    Flyweight(享元模式) 定义 GOF:运用共享技术有效地支持大量细粒度的对象. GOF的定义比较专业化,通俗来说,当你有大量相似的实例时,你把其中相同的实例取出来共享. 例子 在你的游戏场景中 ...

  6. Hbuilder开发HTML5 APP之向导页制作

    研究了下,向导页的制作还是比较简单的,主要使用的是mui控件中的”图片轮播“组件,组件的标签写法手册中有,中间发现个有趣的东西,如果要作全屏,可以加个样式mui-fullscreen 滑动图片时会自动 ...

  7. SQL Server无法收缩日志文件 2 因为逻辑日志文件的总数不能少于 2问题

    SQL Server无法收缩日志文件 2 因为逻辑日志文件的总数不能少于 2问题 最近服务器执行收缩日志文件大小的job老是报错 我所用的一个批量收缩日志脚本 USE [master] GO /*** ...

  8. Code First开发系列实战之使用EF搭建小型博客平台

    返回<8天掌握EF的Code First开发>总目录 本篇目录 理解应用需求 数据库设计 创建实体数据模型 创建实体类 创建关系和导航属性 实现DbContext类 执行数据访问 理解仓储 ...

  9. ABP理论学习之导航(Navigation)

    返回总目录 本篇目录 创建菜单 注册导航提供者 展示菜单 每一个web应用在页面之间都有一些要导航的菜单.ABP提供了公用的基础设施来创建菜单并将菜单展示给用户. 创建菜单 一个应用可能由不同的模块组 ...

  10. iOS开发系列—Objective-C之内存管理

    概述 我们知道在程序运行过程中要创建大量的对象,和其他高级语言类似,在ObjC中对象时存储在堆中的,系统并不会自动释放堆中的内存(注意基本类型是由系统自己管理的,放在栈上).如果一个对象创建并使用后没 ...