代码改变世界

MVC 中T4扫盲贴

2011-11-25 13:41  随风浪迹天涯  阅读(2562)  评论(1编辑  收藏  举报

导读:

AspNet MVC与T4,我定制的视图模板 

ASP.NET MVC T4 模板

 

在我们开发MVC 项目的时候,我们很习惯性的通过“Add View”或者“Add Controller”来进行添加试图和控制器的操作。这些模板试图都是微软帮我们生成好了的,在一般情况可以满足我们的项目,但是如果在特定时候,我们需要自己定义一个模板,来符合自己的项目的需求呢?难道我们需要每一个页面都在微软生成的模板上进行修改吗?非也。

上次看到一个老外的一篇有关这方面的知识,洋文如下,本人不才,很努力的把它翻译了过来。如果哪位洋文好的,可以看下面的。

T4 Templates: A Quick-Start Guide for ASP.NET MVC Developers

以及Scott的 T4 (Text Template Transformation Toolkit) Code Generation - Best Kept Visual Studio Secret

1.模板的位置和模板的重写

首先先上一个add view的图吧:

在上面的Scaffold template中,我可以选择相应的模板(当然 这你需要选中相关“强类型”)。

在我们Add view和Add controller的时候,会弹出一个对话框(比如上面的)执行生成代码的时候会使用到 T4模板。这些模板通过工具是可以被修改以便符合我们自定义的需求。你可以在下面的路径下面找到这些文件: [Visual Studio Install Directory]\Common7\IDE\ItemTemplates\[CSharp | VisualBasic]\Web\MVC\CodeTemplates\

比如说我的是在: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC 3\CodeTemplates\AddView里面。

你可以复制‘CodeTemplates’ 这个文件夹到你项目的根目录下面,然后再每一个项目都进行自定义相关模板(或者,你也可以仅仅只是创建一个CodeTemplates’ 文件夹,然后再里面在创建2个文件夹,名字分别为:‘Add Controller’ 和’Add View’)。需要注意的是 ,如果你愿意,你可以重写一些模板,在你add controller和add view的时候,对话框会优先列出你自己创建的模板。对添加view需要记住的是,你可以在全局设置中或者在你的项目中添加你自己的与.tt为后缀的文件名,它们会在创建试图内容框中自动在下拉列表中显示出来。

需要注意的是,当你拷贝上面的文件夹到你的项目中的时候,你将会看到下面的提醒功能。

点击“Cancel”按钮,因此你不能运行这个T4模板(当你拷贝上面的文件夹的时候,如果你添加了多个.tt结尾的文件,那么你将不得不每次都点击)这是因为只要项目看见.ff结尾的文件,这文件的有一个属性叫CustomTool,它会被设置为TextTemplatingFileGenerator这个值,它是告诉Visual Studio使用默认的T4宿主文件来进行模板 以及在创建一个基于当前模板的新的文件。

这个生成器可以很好的、一次性的根据模板生成相关代码。然后因为‘Add Controller’ 和’Add View’有代码在里面,而这些代码依赖于模板的host文件(等一下你将会看到),执行这些模板通过默认的生成器会产生错误。所以防止这么的错误,你可以先清理Custom Tool 的属性,然后再把模板复制到你的项目中。

注意:如果你想在.tt文件上移除自动设定这个Custom Tool的映射。你可以通过注册表进行修改,需要注意的是如果你想恢复这些键值对到他们的默认值,那么你可以在Visual Studio的安装包装执行一个修复(repair)操作或者手动增加整个备份就可以了。打开注册表的编辑器(“开始” “运行”→“Regedit”),然后你可以导航到下面的位置,这个依赖你的操作系统是32位的还是64位的。

32-bit: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators  

64-bit: HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\9.0\Generators

在Generators’ 文件下直接展开每一个节点,然后寻找以.tt结尾的文件,设定这个注册表的值为:(Defalut)为空,就那么简单。

如果你想覆盖一个全局模板但是又不想复制一个名字为“CodeTemplate”的文件到你的项目中(现在假设你在你项目中已经有了一个同名的文件夹),通过注册表的值你可以改变add Controller和add View的文件夹名字。打开注册表的编辑器(“开始” “运行”→“Regedit”),然后你可以导航到下面的位置,这个依赖你的操作系统是32位的还是64位的。

 32-bit: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\MVC\CodeTemplates  

64-bit: HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\9.0\MVC\CodeTemplates

改变这个值OverrideDir,改成你希望在你项目中运用的值。需要注意的是在下面的这个文件夹你将不得不维持和先前一样的层次结构,有一个文件夹的名“Add Controller’ 或者Add View’。

2.编辑 T4模板

如果你用Visual Studio打开一个.tt文件,你会注意到它们看起来很普通的一些了二进制字符串----没有高亮显示的字符串。我强烈的推荐你下载T4 Editor 这个编辑器。这个编辑是有Clarius Consulting开发的,集成到了Vtudio Studio里面,在你书写T4 语法的时候可以高亮的显示语法和一些基本的T4语句结构。幸运的是,它有一个免费的版本叫‘Community Edition’ 和‘Professional Edition’ 的版本的功能基本是一样的强大,只是Professional Edition’ 比Community Edition’ 的版本多了一个特性比较这个功能。这个插件在膜拜编写的时候真的非常大的帮助,正如你在以下看的图一样:

上面的无高亮显示

有高亮显示

3.剖析一个T4模板

开始编辑一个模板最简单的方式莫过于你去查看在我们VS自带的默认模板的工作方式。因此,我们打算在’Add View‘下面的一个叫’Create‘(Create.tt)模板的一些细节进行介绍。首先看一下这个模板的头部:

这里总共有四行:

1.第一行使模板的指示符(directive),它主要的工作就是告诉T4引擎它所使用的语言。当我们指定这个模板的语言的时候,我们并不意外着我们输出的时候是用这门语言写的,而是仅仅指的是一些控制性质的代码(比如说,你的模板也许包括一个 if/else 语句的条件判断语句)。HostSpecific’属性必须要设置为“True”,否则的话这个模板在你添加“Controller”和添加“View”时对话中的的相关信息不能被读取到(其实这个事情就像强类型那种绑定)。

2,接着下一行输出指示符,它通告这个模板的宿主文件,然后简单的为输出文件设定一个默认的后缀名---但是它和MVC 工具并没有特定的关系,因为MVC 是依赖相关的环境,所以这个后缀名也许会被忽略掉(比如说,如果我们处理一个partial view的时候,这个文件的后缀名是.ascx)。

 3.接下来的2行使导入指示符,它们就像C#中的using和VB中的import语句。如果你的模板代码中使用了相关的类文件,那么你需要导入它们。

你可以在这里查找一些T4指示符的文档: http://msdn.microsoft.com/en-us/library/bb126421.aspx

然后 接着往下看,你会注意到有这么一行代码:

在这一行的意思是说我们创建了一个新的变量并且命名为:’mvcHost‘,然后指定它转换成一个’Host‘类型。这个’Host‘属性有的时候会自动的加载进模板里面,因为我们在上面的’HostSpecific’ 属性设置为‘True’。MVC 工具提供了一个自定义的host文件,以便可以从工具外面递一些信息到这个模板里。为了访问我们提供的host类的属性,这个‘Host’属性被强制转换成我们的host类型的,也就是‘MvcTextTemplateHost’类型。

我们怎么使用这个变量(mvcHost)呢?事实上它很直接了当的告诉你:

第一件事情你需要注意的是 这里有一个<#和 #>这个标记。这些标记我们称为语句块,主要是用在控制代码上面。在你的模板里,也许你仅仅只是想要有条件的输出一些相关的文本块到输出文件中和阻止一些其他文本快被输出。就像在上图中显示,我们使用了一个if语句(用C#语法写的,因为我们在模板的语言指示符这里设置了C#),通过一对大括号({})进行打开和关闭。特别需要注意的是if语句在host文件中访问调用了一个叫’IsViewUserControl’的方法,这个方法告诉模板如果一个用户选择了一个partial view的时候 执行if里面的操作。

所以在控制语句外面的文本都会最终被输出到最终的文件中。比如在我们上面的截图,14行的文本在任何语句块的外面,因此它是输出的一部分--然而它只有在12行语句为‘True’的情况下才能背输出到指定的文本中。

你可以读更多的有关T4 语句块的资料:

在T4模板中最简单的方式理解这些控制代码是,你可以把他们组合起来在你的头脑中想象成一个完整的程序。我在第6行中使用的声明的变量,在T4模板里面的后面被使用----每一个if/else条件分支增加了输出到最终文件的文本。

任何我们接着往下走,我们很惊奇的看见下面的代码:

我们声明了一个类型为List<string>的变量并且命名为“properties”的变量。我怎么能在T4模板中使用List类型的?因为我在模板的顶部导入了文件:

第56行被我们定义了一个叫‘FilterProperties’的方法---但是这个方法在哪里呢?其实,它在我们这个模板的顶部。

如果你看的比较仔细的话,这个并不像语句快(<# #>),这个代码快是'<#+'这个开始的。这个就是我们所熟知的类特性语句块。

他们的工作是这样子的:T4 在你的模板里获取所有的类特性,然后把他们加入到类中,这个类在后台被进行编译。这种工作不仅仅局限于方法,而且在属性中也是这么用的。就像在一个平常的类中的成员,现在这些(被编译的代码)在其他的模板中可以访问。

读更多有关类特性模板:http://msdn.microsoft.com/en-us/library/bb126541.aspx

在上面的截图中,我们的默认模板使用的是’FilterProperties’ 方法然后默认的为一些类型的属性输出标记---也就是说这些事公共方法,将会被在设计视图中显示,比如说GridView等等。这个逻辑是一样的,就像你将获取来自GridView.IsBindableType的方法的数据。

这个IsBindableType方法在136行被调用,不过它的定义却在模板的顶部。

如果你想改变我们模板过滤的属性,那么你可以修改方法,直到你喜欢。 好了,最后让我们看一下 65行代码:

在这里,我们又出现了一个新的结构:'<#='.这个叫做表达式语句块(expression block),它的作用是从T4代码中插入值然后输出文本。正如你上面看到的,我们有一个foreach循环,它迭代了所有的属性以及定义了一个本地变量叫‘propertyName’。因为我们想为没一个属性输出<th>标签,所以我们使用表达式块。

你可以查找到更多的表达式快:

正如你所见,在T4模板里面你可以通过多种方式来选择输出文本,因此T4在自动代码生成以及灵活的定制输出文本方面是一个非常强有力的工具。

4.MVC Tools T4 Host Properties

通过这个模板host文件中,Add Controller 和Add View对话框每次显示不同的属性。正如我们在上面的Create模板中的片段。这些是在模板 host文件中所有的可用的属性,供你的模板使用。

Add Controller:

Property   Name

Type

Description

ItemName

System.String

控制器类名,包括控制器的后缀

NameSpace

System.String

这控制器生成所需要的命名空间

ExtraActionMethods

System.Boolean

提示用户在add controller对话框获取额外的action方法的时候是否需要检查

ControllerRootName

System.String

controller的类名没有后缀

Add View:

Property Name

Type

Description

ItemName

System.String

The name of the view (without extension), as typed in the Add   View dialog

NameSpace

System.String

The default namespace of the view’s parent folder

IsViewUserControl

System.Boolean

Evaluates to true if the user chose a partial view in the Add   View dialog

IsViewContentPage

System.Boolean

Evaluates to true if the user is creating a view with a master   page

IsViewPage

System.Boolean

Evaluates to true if the user is creating a regular view page

MasterPage

System.String

Path to the master page the user chose in the dialog (to be used   only when IsViewContentPage is true)

ContentPlaceholder

System.String

Name of the primary content place holder into which the   generated content will be placed. This is the content place holder id the   user typed into the Add View dialog

ContentPlaceHolders

System.Collections.Generic.List<System.String>

A list of all content place holder ID’s in the master page, if a   master page was chosen for this view

LanguageExtension

System.String

The output file’s extension (including the period)

ViewDataTypeGenericString

System.String

This is a string that is used to output the generics clause for   the ‘Inherits’ attribute in the view's directive (for strongly-typed views).   Example: “<MyType>” or “(Of MyType)”

ViewDataType

System.Type

This is a Type object representing the type to which a   strongly-typed view is bound. It can be used to get information on the   properties in the type and the like

此外。有一些属性在默认的Host属性中是默认的属性,也许对你有用,比如这个当前模板执行的路径。

你可以在这里找到更多有关资料: http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.texttemplating.itexttemplatingenginehost_properties.aspx

5.总结:

我们希望这篇文章可以带给你T4的足够信息以及怎么有效的使用他们结合ASP.NET MVC可视化Web 开发工具

 

 累死了,弄我一个上午,希望对你们有用。