個人網站地址:nee32.com 一、T4模板內容簡介 為了更好地學習T4模板,我們安裝一個插件tangible T4 Editor 在使用了EF生成實體類後,我們會發現一個.tt尾碼的文件,它就是T4模板,直接打開 它的內容如下圖: 就是這一個模板,生成了我們需要的類,省去了我們手寫的麻煩,提高了 ...
個人網站地址:nee32.com
一、T4模板內容簡介
為了更好地學習T4模板,我們安裝一個插件tangible T4 Editor 在使用了EF生成實體類後,我們會發現一個.tt尾碼的文件,它就是T4模板,直接打開 它的內容如下圖:
就是這一個模板,生成了我們需要的類,省去了我們手寫的麻煩,提高了工作效率,生成的實體類如下圖:
那麼,這些類是如何用T4模板生成出來的?要自定義模板又該如何操作?
下麵來簡單介紹下T4模板中的核心代碼
1、全局變數申明
<#@ template language="C#" debug="false" hostspecific="true"#> //模板指令集 告訴編輯器這是一個模板 用C#語言, <#@ include file="EF.Utility.CS.ttinclude"#> //導入外部的模板 <#@ output extension=".cs"#> //輸出擴展名為.cs的文件
上面段代碼就是定義要用到的全局變數(如 要映射類的EDMX文件、引用名稱空間、實體類集合等...)
2、生成類頂部註釋、實體類名稱空間 及 實體類名稱和尾碼名
WriteHeader(codeStringGenerator, fileManager);//生成類中的最頂部註釋 foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection)) { fileManager.StartNewFile(entity.Name + ".cs");//生成類名稱以及加.cs尾碼名稱 BeginNamespace(code);//生成類名稱空間 ... }
這句代碼生成的相應類文件如下圖
3、引用空間名稱 UsingDirectives 方法
public string UsingDirectives(bool inHeader, bool includeCollections = true) { return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion()) ? string.Format( CultureInfo.InvariantCulture, "{0}using System;{1}" + "{2}", inHeader ? Environment.NewLine : "", includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "", inHeader ? "" : Environment.NewLine) : ""; }
預設引用了System和System.Collections.Generic,如下圖:
4、定義類名 EntityClassOpening方法
public string EntityClassOpening(EntityType entity) { return string.Format( CultureInfo.InvariantCulture, "{0} {1}partial class {2}{3}", Accessibility.ForType(entity), _code.SpaceAfter(_code.AbstractOption(entity)), _code.Escape(entity), _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType))); }
Accessibility.ForType(entity) 訪問修飾符,_code.Escape(entity) 類名稱 ,如下圖:
5、生成欄位屬性 Property方法
public string Property(EdmProperty edmProperty) { return string.Format( CultureInfo.InvariantCulture, "{0} {1} {2} {{ {3}get; {4}set; }}", Accessibility.ForProperty(edmProperty), _typeMapper.GetTypeName(edmProperty.TypeUsage), _code.Escape(edmProperty), _code.SpaceAfter(Accessibility.ForGetter(edmProperty)), _code.SpaceAfter(Accessibility.ForSetter(edmProperty))); }
Accessibility.ForProperty(edmProperty) 訪問修飾符, _typeMapper.GetTypeName(edmProperty.TypeUsage) 欄位數據類型,如下圖:
二、T4模板拓展 繼承基類、介面
一般我們在基類中定義一些通用的方法,讓子類直接繼承使用,先定義如下基類:
public class IEntity<T> where T : class , new() { private DbContext db { get { return EFDbContextFactory.GetCurrentDbContext(); } } /// <summary> /// 根據條件查找 /// </summary> /// <param name="where"></param> /// <returns></returns> public T Find(Expression<Func<T, bool>> where = null) { if (where == null) return db.Set<T>().FirstOrDefault(); else return db.Set<T>().Where(where).FirstOrDefault(); } }
直接修改T4模板中的 定義類名 EntityClassOpening 方法,繼承基類的Find方法,修改後的代碼如下:
public string EntityClassOpening(EntityType entity) { return string.Format( CultureInfo.InvariantCulture, "{0} {1}partial class {2}{3} : IEntity<{2}>", Accessibility.ForType(entity), _code.SpaceAfter(_code.AbstractOption(entity)), _code.Escape(entity), _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType))); }
然後直接保存一下,再查看T4模板生成的類,發現它們都自動繼承了IEntity類,如下圖
調用 ,直接B_Article model = new B_Article().Find(c => c.UserName == "tess");