T4模板创建多文件使用方法(二)---创建多文件
前面一篇讲的T4的使用基础T4模板生成多文件使用(一)--T4简介
现在开始总计一个创建多文件的历程
第一次:使用代码如下,创建的结果是可以生成多文件
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#><# //引用模板文件#>
<#@ output extension=".cs"#><# //设置文件输出类型为.cs#>
<#
var loader = new MetadataLoader(this);
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
//获取Model中的所有的edmx文件
var edmxPath=Host.ResolveAssemblyReference("$(SolutionDir)")+@"Jerry_Project_FA_Model\";
var fileInfos =new DirectoryInfo(edmxPath).GetFiles("*edmx");
#>
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码已从模板生成。
//
// 手动更改此文件可能导致应用程序出现意外的行为。
// 如果重新生成代码,将覆盖对此文件的手动更改。
// </auto-generated>
//------------------------------------------------------------------------------
<#
foreach(var file in fileInfos)
{
string contextStr=file.Name.Split('.')[0];//获取文件的name
var ItemCollection =loader.CreateEdmItemCollection(file.FullName);//用来获取edmx文件中的实体类
foreach(EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e=>e.Name)) {
fileManager.StartNewFile(entity.Name + "Service.cs");
#>
//在这位置写你想要在文件中生成的代码
//比如:
//using System;
//namespapce MyNamespace{
//这个生成的时候最好要使用partial修饰符,以为如果以后你要手动拓展这个类型的话,
//代码不能写在这个里面(重新生成T4模板,全部会被覆盖),需要重新在创建一个部分类
// public partial class MyClass{
// }
//}
<#
}
}
//让下面这一句和,创建fileManager对象的语句放在一个代码块中
fileManager.Process();
#>
每个生成文件中的代码如下
弊端:假如存在多个edmx文件的话,这些edmx文件的中的类都会生成到一个文件下面,这样看起来就会非常的难看,这并不是我想要的结果,就像下面一样,左侧Model文件夹下面有两个edmx文件,右侧生成的文件全部在一个目录下面
第二次:为每个edmx文件创建创建一个T4模板
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#><# //引用模板文件#>
<#@ output extension=".cs"#><# //设置文件输出类型为.cs#>
<#
var loader = new MetadataLoader(this);
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
var edmxName="UserInfoModel";
//获取Model中的所有的edmx文件
var edmxPath=Host.ResolveAssemblyReference("$(SolutionDir)")+@"Jerry_Project_FA_Model\"+edmxName+".edmx";
#>
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码已从模板生成。
//
// 手动更改此文件可能导致应用程序出现意外的行为。
// 如果重新生成代码,将覆盖对此文件的手动更改。
// </auto-generated>
//------------------------------------------------------------------------------
<#
var ItemCollection =loader.CreateEdmItemCollection(edmxPath);//用来获取edmx文件中的实体类
foreach(EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e=>e.Name)) {
fileManager.StartNewFile(entity.Name + "Service.cs");
#>
//在这位置写你想要在文件中生成的代码
//比如:
//using System;
//namespapce myNamespace{
//这个生成的时候最好要使用partial修饰符,以为如果以后你要手动拓展这个类型的话,
//代码不能写在这个里面(重新生成T4模板,全部会被覆盖),需要重新在创建一个部分类
// public partial class my class{
// }
//}
<#
}
//一定要放在foreach(var entity in ItemCollection.GetItems<EntityType>().OrderBy(e=>e.Name))循环外面
fileManager.Process();
#>
这个的话文件就会存在不同的T4文件下面,看起来就会舒服的多
弊端:每次新建一个edmx文件的话就需要在重新创建一套T4模板,虽然只是复制,粘贴,改个变量值,但这个不是想要的
第三次:最后想,是不是可以动态创建T4模板,然后再让动态创建的T4模板,生成想要的类型
通过验证,证明这个想法是可以实现的选择转换所有T4模板时,动态生成的T4模板也可以转换(膜拜一下VS)
使用时需要注意的是,要写入动态生成的T4模板中的T4指令需要用"\"转义字符进行转义
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ output extension=".cs"#>
<#
MetadataLoader loader = new MetadataLoader(this);
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
var edmxList =new DirectoryInfo(Host.ResolveAssemblyReference("$(SolutionDir)")+@"Jerry_Project_FA_Model\").GetFiles("*.edmx");//修改路径,也可以在配置文档中定义
foreach(var file in edmxList){
string edmxName = file.Name.Split('.')[0];
fileManager.StartNewFile("I"+edmxName+ "DALGenerator.tt");
#>
\<#
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码已从模板生成。
//
// 手动更改此文件可能导致应用程序出现意外的行为。
// 如果重新生成代码,将覆盖对此文件的手动更改。
// </auto-generated>
//------------------------------------------------------------------------------
\#>
\<#@ template language="C#" debug="false" hostspecific="true"
\#>
\<#@ include file="EF.Utility.CS.ttinclude"
\#>
\<#@ output extension=".cs"
\#>
\<#
MetadataLoader loader = new MetadataLoader(this);
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
string modelName="<#=edmxName#>";
string fileName=@"<#=file.FullName#>";
EdmItemCollection ItemCollection =loader.CreateEdmItemCollection(fileName);
\#>
\<#
foreach(EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e=>e.Name)) {
fileManager.StartNewFile("I"+entity.Name + "Dal.cs");
\#>
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码已从模板生成。
//
// 手动更改此文件可能导致应用程序出现意外的行为。
// 如果重新生成代码,将覆盖对此文件的手动更改。
// </auto-generated>
//------------------------------------------------------------------------------
using Jerry_Project_FA_Model;
using Jerry_Libr_Framework_Core.BaseDAL;
namespace Jerry_Project_FA_IDAL.\<#=modelName\#>
{
public partial interface I\<#=entity.Name\#>Dal:IBaseDal<\<#=entity.Name\#>>
{
}
}
\<#
}
fileManager.Process(true);
\#>
<#
}
fileManager.Process(true);
#>
生成的目录结构如下:在codeGenerator下会动态生成T4模板
生成的T4模板中的代码如下
<#
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码已从模板生成。
//
// 手动更改此文件可能导致应用程序出现意外的行为。
// 如果重新生成代码,将覆盖对此文件的手动更改。
// </auto-generated>
//------------------------------------------------------------------------------
#>
<#@ template language="C#" debug="false" hostspecific="true"
#>
<#@ include file="EF.Utility.CS.ttinclude"
#>
<#@ output extension=".cs"
#>
<#
MetadataLoader loader = new MetadataLoader(this);
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
string modelName="UserInfoModel";
string fileName=@"E:\MyCode20180714\Jerry_Project_FA\Jerry_Project_FA\Jerry_Project_FA_Model\UserInfoModel.edmx";
EdmItemCollection ItemCollection =loader.CreateEdmItemCollection(fileName);
#>
<#
foreach(EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e=>e.Name)) {
fileManager.StartNewFile("I"+entity.Name + "Dal.cs");
#>
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码已从模板生成。
//
// 手动更改此文件可能导致应用程序出现意外的行为。
// 如果重新生成代码,将覆盖对此文件的手动更改。
// </auto-generated>
//------------------------------------------------------------------------------
using Jerry_Project_FA_Model;
using Jerry_Libr_Framework_Core.BaseDAL;
namespace Jerry_Project_FA_IDAL.<#=modelName#>
{
public partial interface I<#=entity.Name#>Dal:IBaseDal<<#=entity.Name#>>
{
}
}
<#
}
fileManager.Process(true);
#>
动态生成的T4模板又会生成新的文件,代码如下
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码已从模板生成。
//
// 手动更改此文件可能导致应用程序出现意外的行为。
// 如果重新生成代码,将覆盖对此文件的手动更改。
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Jerry_Project_FA_Model;
using Jerry_Libr_Framework_Core.BaseDAL;
namespace Jerry_Project_FA_IDAL.UserInfoModel
{
public partial interface IActionInfoDal:IBaseDal<ActionInfo>
{
}
}
这样就解决上面的两个问题,假如在Model文件夹下添加了新的edmx文件,只需要重新转换T4模板,即可