[转]MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码
2020-12-13 01:39
标签:des style blog class code java 本文转自:http://www.cnblogs.com/guomingfeng/p/mvc-ef-t4.html 一、前言 二、工具准备 三、T4代码生成预热 (一) 单文件生成:HelloWorld.cs (二) 多文件生成 四、生成数据层实体相关相似代码 (一) 生成准备 (二) 生成实体相关相似代码 五、源码获取 系列导航 经过前面EF的《第一篇》与《第二篇》,我们的数据层功能已经较为完善了,但有不少代码相似度较高,比如负责实体映射的
EntityConfiguration,负责仓储操作的IEntityRepository与EntityRepository。而且每添加一个实体类型,就要手动去添加一套相应的代码,也是比较累的工作。如果能有一个根据实体类型自动生成这些相似度较高的代码的解决方案,那将会减少大量的无聊的工作。 VS提供的“文本模板”(俗称T4)功能,就是一个较好的解决方案。要添加一个实体类型,只要把实体类型定义好,然后运行一下定义好的T4模板,就可以自动生成相应的类文件。 为了更好的使用 T4模板 功能,我们需要给VS安装如下两个插件: 下面,我们先来体验一个最简单的T4代码生成功能,输出一个最简单的类文件。 首先,在 GMF.Demo.Core.Data中 添加一个名为 T4 的文件夹,用于存放生成本工程内的代码的T4模板文件。并在其中添加一个名为
HelloWorld.tt的“文本模板”的项。 HelloWorld.tt定义如下: 直接保存文件(T4的生成将会在保存模板,模板失去焦点等情况下自动触发生成。),将会在模板的当前位置生成一个同名的类文件: HelloWorld.cs的内容如下: 这样,我们的HelloWorld之旅就结束了,非常简单。 当前位置方案的方案只能生成如下所示的代码: 生成的文件会与T4模板在同一目录中,这里就不详述了,可以参考 蒋金楠 一个简易版的T4代码生成"框架" 。 本项目的多文件需要生成到指定文件夹中,但又想对T4模板进行统一的管理,T4文件夹里放置T4模板文件,但生成的映射文件EntityConfiguration将放置到文件夹Configurations中,仓储操作的文件IEntityRepository与EntityRepository将放置到Repositories文件夹中。且生成的代码文件应能自动的添加到解决方案中,而不是只是在文件夹中存在。 要实现此需求,一个简单的办法就是通过 T4 Toolbox 来进行生成。想了解 T4 Toolbox 的细节,可以自己使用 ILSpy
来对 T4Toolbox.dll 文件进行反编译来查看源代码,如果是通过 T4 Toolbox
是通过VS的插件来安装的,将在“C:\Users\Administrator\AppData\Local\Microsoft\VisualStudio\11.0\Extensions\dca4f0lt.jdx”文件夹中(我的机器上)。下面,我们直接进行多文件生成的演示。 首先,添加一个名为 HelloWorldTemplate.tt 的 T4 Toolbox 的代码模板。 此模板将继承于 T4 Toolbox 的 CSharpTemplate 类: 模板类中定义了一个 className 参数,用于接收一个表示要生成的类名的值。所有生成类的代码都以字符串的形式写在重写的
TransformText 方法中。 再定义一个T4模板文件 HelloWorldMulti.tt,用于调用 上面定义的代码模板进行代码文件的生成。 以上是整个T4模板的执行方,在执行方中,要引用所有需要用到的类库文件,命名空间,包含的模板文件等。 最后,文件的生成是调用 T4 Toolbox 的Template基类中定义的 RenderToFile(string
filename)方法来生成各个文件的,输入的参数为生成文件的文件全名。在这里,生成将如下所示: outPPath文件夹中生成了 HelloWorld1.cs、HelloWorld2.cs、HelloWorld3.cs
文件,而 HelloWorldMulti.tt
所在文件夹中也会生成一个空的 HelloWorldMulti.cs 类文件。 我们的生成代码是完全依赖于业务实体的,所以,需要有一个类来对业务实体的信息进行提取封装。 另外,通过模板生成的代码,与我们手写的代码有如下几个区别: 基于以上几个区别,我提出如下解决方案,来解决生成代码的修改问题 实体映射配置类模板 EntityConfigurationTemplate.tt 定义: 生成模板调用方 EntityCodeScript.tt 定义 调用方通过反射从业务实体程序集 GMF.Demo.Core.Models.dll 中获取所有基类为 Entity
的并且不是抽象类的实体类型信息,再调用模板逐个生成实体配置类文件。 例如,生成的登录记录信息(LoginLog)的映射文件 LoginLogConfiguration.generated.cs 如下: 要配置登录信息与用户信息的 N:1
关系,只需要添加一个分部类 LoginLogConfiguration,并实现分类方法 LoginLogConfigurationAppend
即可。 实体映射配置类模板 EntityConfigurationTemplate.tt 定义: 相应的,在调用方 EntityCodeScript.tt 中添加模板调用代码(如下 11-15 行所示): 生成的登录记录信息仓储操作接口 ILoginLogRepository.generated.cs: [转]MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码,搜素材,soscw.com [转]MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码 标签:des style blog class code java 原文地址:http://www.cnblogs.com/freeliver54/p/3709743.html〇、目录
一、前言
二、工具准备
三、T4代码生成预热
(一) 单文件生成:HelloWorld.cs
1 "false" hostspecific="false" language="C#" #>
2 "System.Core" #>
3 namespace="System.Linq" #>
4 namespace="System.Text" #>
5 namespace="System.Collections.Generic" #>
6 ".cs" #>
7 using System;
8
9 namespace GMF.Demo.Core.Data.T4
10 {
11 public class HelloWorld
12 {
13 private string _word;
14
15 public HelloWorld(string word)
16 {
17 _word = word;
18 }
19 }
20 }
1 using System;
2
3 namespace GMF.Demo.Core.Data.T4
4 {
5 public class HelloWorld
6 {
7 private string _word;
8
9 public HelloWorld(string word)
10 {
11 _word = word;
12 }
13 }
14 }
(二) 多文件生成
1 2 //
1 "false" hostspecific="false" language="C#" #>
2 "System.Core" #>
3 namespace="System.IO" #>
4 namespace="System.Linq" #>
5 namespace="System.Text" #>
6 namespace="System.Collections.Generic" #>
7 "T4Toolbox.tt" #>
8 "HelloWorldTemplate.tt" #>
9 #
10 string curPath = Path.GetDirectoryName(Host.TemplateFile);
11 string destPath = Path.Combine(curPath, "outPath");
12 if(!Directory.Exists(destPath))
13 {
14 Directory.CreateDirectory(destPath);
15 }
16 string[] classNames = new[]{"HelloWorld1", "HelloWorld2", "HelloWorld3"};
17 foreach(string className in classNames)
18 {
19 HelloWorldTemplate template = new HelloWorldTemplate(className);
20 string fileName = string.Format(@"{0}\{1}.cs", destPath, className);
21 template.Output.Encoding = Encoding.UTF8;
22 template.RenderToFile(fileName);
23 }
24 #>
四、生成数据层实体相关相似代码
(一) 生成准备
1 namespace GMF.Component.Tools.T4
2 {
3 ///
(二) 生成实体相关相似代码
1. 生成实体映射配置类
1 2 //
1 "C#" debug="True" #>
2 "cs" #>
3 "System.Core" #>
4 "$(SolutionDir)\GMF.Component.Tools\bin\Debug\GMF.Component.Tools.dll" #>
5 namespace="System.IO" #>
6 "System.Linq" #>
7 "System.Text" #>
8 namespace="System.Reflection" #>
9 "System.Collections.Generic" #>
10 "GMF.Component.Tools" #>
11 "GMF.Component.Tools.T4" #>
12 "T4Toolbox.tt" #>
13 "Include\EntityConfigurationTemplate.tt" #>
14 #
15 string currentPath = Path.GetDirectoryName(Host.TemplateFile);
16 string projectPath =currentPath.Substring(0, currentPath.IndexOf(@"\T4"));
17 string solutionPath = currentPath.Substring(0, currentPath.IndexOf(@"\GMF.Demo.Core.Data"));
18
19 string modelFile= Path.Combine(solutionPath, @"GMF.Demo.Core.Models\bin\Debug\GMF.Demo.Core.Models.dll");
20 byte[] fileData= File.ReadAllBytes(modelFile);
21 Assembly assembly = Assembly.Load(fileData);
22 IEnumerable
1 //------------------------------------------------------------------------------
2 //
3 // 此代码由工具生成。
4 // 对此文件的更改可能会导致不正确的行为,并且如果
5 // 重新生成代码,这些更改将会丢失。
6 // 如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类实现 LoginLogConfigurationAppend 分部方法。
7 //
8 //
9 //
1 namespace GMF.Demo.Core.Data.Configurations
2 {
3 partial class LoginLogConfiguration
4 {
5 partial void LoginLogConfigurationAppend()
6 {
7 HasRequired(m => m.Member).WithMany(n => n.LoginLogs);
8 }
9 }
10 }
2. 生成实体仓储接口
1 2 //
1 foreach(Type modelType in modelTypes)
2 {
3 T4ModelInfo model = new T4ModelInfo(modelType);
4
5 //实体映射类
6 EntityConfigurationTemplate config = new EntityConfigurationTemplate(model);
7 string path = string.Format(@"{0}\Configurations", projectPath);
8 config.Output.Encoding = Encoding.UTF8;
9 config.RenderToFile(Path.Combine(path, config.FileName));
10
11 //实体仓储操作接口
12 IEntityRepositoryTemplate irep= new IEntityRepositoryTemplate(model);
13 path = string.Format(@"{0}\Repositories", projectPath);
14 irep.Output.Encoding = Encoding.UTF8;
15 irep.RenderToFile(Path.Combine(path, irep.FileName));
16 }
1 //------------------------------------------------------------------------------
2 //
3 // 此代码由工具生成。
4 // 对此文件的更改可能会导致不正确的行为,并且如果
5 // 重新生成代码,这些更改将会丢失。
6 // 如存在本生成代码外的新需求,请在相同命名空间下创建同名分部类进行实现。
7 //
8 //
9 //
文章标题:[转]MVC实用架构设计(三)——EF-Code First(3):使用T4模板生成相似代码
文章链接:http://soscw.com/essay/23971.html