CodeFirst时使用T4模板
我们都知道T4模板用于生成相似代码。
在DBFirst和ModelFirst条件下我们很容易从.edmx下获取所有实体类和其名称,并且通过我们定义的模板和某些遍历工作为我们生成所需要的相似代码。
但是CodeFirst模式下,我们没有edmx,从哪获取所有类名呢?难道要我们一个个把Entity实体层类名写进数组里吗,十个百个千个?
解决过程:
1.使用反射获取所有类名,并将此段代码写到T4模板中。
foreach (Type t in Assembly.Load("Entity").GetTypes()) { //你对这些类信息的操作 //e.g: if (t.FullName == "Entity.baseEntity") { } else { string fullName = t.FullName; int length = fullName.Length; int index = fullName.LastIndexOf('.'); string classname = fullName.Substring(index + 1, length - index - 1); nameStr += (classname) + ","; } }
2.结果如上代码可以加载程序集并且获取所有类名,可以自行断点查看。当我们把这段代码放到T4模板中,报错信息却是不能加载程序集。(看见了运行时文本模板,还没尝试那个模板是否有效)
3.最后实在没办法了,我在应用中创建了一个名为HelpTool的控制台程序。讲上段代码在Main中改写如下:
static void Main(string[] args) { using (StreamWriter writer = new StreamWriter("D:\\EntitiesNames.txt")) { string classNameStr = ""; foreach (Type t in Assembly.Load("Entity").GetTypes()) { if (t.FullName == "Entity.BaseEntity" || t.FullName == "Entity.DbContextFactory" || t.FullName == "Entity.WeDbContext") { } else { string fullName = t.FullName; int length = fullName.Length; int index = fullName.LastIndexOf('.'); string classname = fullName.Substring(index + 1, length - index - 1); classNameStr += (classname) + ","; } } writer.Write(""); writer.Write(classNameStr); //Console.WriteLine("WriteClassNameSuccessfully"); //Console.ReadKey(); } }
4.很明确,我将它写到文本文件里,每次修改实体类,我都要运行一下我的控制台应用。
5.在T4模板中读取文本文件。例如:
得到所有实体类的名,存到数组中,并遍历生成相似代码。
<#@ template language="C#" debug="false" hostspecific="true"#> <#@ include file="EF.Utility.CS.ttinclude"#> <#@ output extension=".cs"#> <# string[] className=new string[]{""}; using (StreamReader reader = new StreamReader("D:\\EntitiesNames.txt")) { string nameStr = reader.ReadToEnd(); int index=nameStr.LastIndexOf(','); nameStr=nameStr.Substring(0,index); className= nameStr.Split(','); } #> using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using DalFactory; using Entity; using s2s.IDAL; namespace s2s.UnitOfWork { public partial class UnitWork { <# foreach (var entity in className) { #> public I<#=entity#>Dal <#=entity#>Dal { get { return AbstractDalFactory.GetInstance("<#=entity#>Dal") as I<#=entity#>Dal; } } <#}#> } }
我知道这个方法很笨,谈不上好方案,在遇到问题,coder们总能提出各种各样的解决方案。
希望园子里的朋友们推荐好的方案,多多指教。