• 从零开始编写自己的C#框架(13)——T4模板在逻辑层中的应用(二)


    最近这段时间特忙,公事私事,忙得有时都没时间打开电脑了,这两周只能尽量更新,以后再将章节补回来。

      直接进入主题,通过上一章节,大家明白了怎么使用模板类编写T4模板,本章进的是一些简单技巧的应用

      1、首先创建一个Test2.tt模板

      

      2、然后修改模板内容为下面代码

      这些代码与上一章最后面的那个差不多,只是修改了输出文件名、命名空间、类名、类属性(partial)和一个单例获取函数

    复制代码
     1 <#@ template debug="false" hostspecific="True" language="C#" #>
     2 <#@ output extension=".cs" encoding="utf-8" #>
     3 <#@ include file="SQLServer.ttinclude" #>
     4 <#@ include file="MultipleOutputHelper.ttinclude"#> 
     5 
     6 <#
     7     //获取所有表与视图
     8     var tables = LoadTables();
     9     //创建多文件生成实体
    10     var manager = Manager.Create(Host, GenerationEnvironment);  
    11 
    12     //遍历所有表
    13     foreach(var tbl in tables){
    14         //判断当前表名是否是禁用名称(禁用的名称可以在Settings.ttinclude文件的ExcludeTables字符串数据中进行添加)
    15         if(!ExcludeTables.Contains(tbl.Name))
    16         {
    17             // 设置输出的文件名
    18             manager.StartNewFile(tbl.ClassName+"Bll.cs");
    19 #> 
    20 using System;
    21 
    22 namespace Solution.Logic {
    23 
    24     public partial class <#=tbl.CleanName#>Bll {
    25         
    26         #region 单例模式
    27         //定义单例实体
    28         private static <#=tbl.Name#>Bll _<#=tbl.Name#>Bll = null;
    29 
    30         /// <summary>
    31         /// 获取本逻辑类单例
    32         /// </summary>
    33         /// <returns></returns>
    34         public static <#=tbl.Name#>Bll GetInstence() {
    35             if (_<#=tbl.Name#>Bll == null) {
    36                 _<#=tbl.Name#>Bll = new <#=tbl.Name#>Bll();
    37             }
    38             return _<#=tbl.Name#>Bll;
    39         }
    40         #endregion
    41         
    42     }
    43 
    44 }
    45 
    46 
    47 <# 
    48             // 输出文件结束
    49             manager.EndBlock();
    50         } //if(!ExcludeTables.Contains(tbl.Name)) 判断结束
    51        
    52     }// end foreach
    53 
    54     // 执行编译,生成文件
    55     manager.Process(true);  
    56 #> 
    复制代码

      运行模板,测试看看效果

      

      

      从上面添加函数的方法可以看出,对于常用的函数,都可以在模板中进行添加后,直接生成出来,这样就减少了程序员很大的工作量了

      3、用上面方法确实可以解决很大部分的问题,但对于一些特殊的函数直接这样写就不行了,比如我们想生成一个删除指定外键Id的函数,由于有的表有外键有的没有,那么就要用上一些简单的判断来处理了

      

    复制代码
     1 <#@ template debug="false" hostspecific="True" language="C#" #>
     2 <#@ output extension=".cs" encoding="utf-8" #>
     3 <#@ include file="SQLServer.ttinclude" #>
     4 <#@ include file="MultipleOutputHelper.ttinclude"#> 
     5 
     6 <#
     7     //获取所有表与视图
     8     var tables = LoadTables();
     9     //创建多文件生成实体
    10     var manager = Manager.Create(Host, GenerationEnvironment);  
    11 
    12     //遍历所有表
    13     foreach(var tbl in tables){
    14         //判断当前表名是否是禁用名称(禁用的名称可以在Settings.ttinclude文件的ExcludeTables字符串数据中进行添加)
    15         if(!ExcludeTables.Contains(tbl.Name))
    16         {
    17             // 设置输出的文件名
    18             manager.StartNewFile(tbl.ClassName+"Bll.cs");
    19 #> 
    20 using System;
    21 using Solution.DataAccess.DataModel;
    22 using Solution.DataAccess.DbHelper;
    23 
    24 namespace Solution.Logic {
    25 
    26     public partial class <#=tbl.CleanName#>Bll {
    27         
    28         #region 单例模式
    29         //定义单例实体
    30         private static <#=tbl.Name#>Bll _<#=tbl.Name#>Bll = null;
    31 
    32         /// <summary>
    33         /// 获取本逻辑类单例
    34         /// </summary>
    35         /// <returns></returns>
    36         public static <#=tbl.Name#>Bll GetInstence() {
    37             if (_<#=tbl.Name#>Bll == null) {
    38                 _<#=tbl.Name#>Bll = new <#=tbl.Name#>Bll();
    39             }
    40             return _<#=tbl.Name#>Bll;
    41         }
    42         #endregion
    43         
    44             
    45 <#
    46         foreach(var col in tbl.Columns){
    47             //判断字段名称中是否包含“_Id”这个字符串,且字段类型为int或long的,则生成对应的删除函数
    48             if (col.CleanName.IndexOf("_Id") >= 0  && (col.SysType == "int" || col.SysType == "long"))
    49             {
    50 #>
    51         #region 删除<#=tbl.Name#>表指定<#=col.CleanName#>的字段值记录
    52         /// <summary>
    53         /// 删除<#=tbl.Name#>表指定<#=col.CleanName#>的字段值记录
    54         /// </summary>
    55         /// <param name="id">记录的主键值</param>
    56         public void DeleteBy<#=col.CleanName#>(int id) {
    57             //删除
    58             <#=tbl.Name#>.Delete(x => x.<#=col.CleanName#> == id);
    59         }
    60 
    61         /// <summary>
    62         /// 删除<#=tbl.Name#>表指定<#=col.CleanName#>的字段值记录
    63         /// </summary>
    64         /// <param name="id">记录的主键值</param>
    65         public void DeleteBy<#=col.CleanName#>(int[] id) {
    66             if (id == null) return;
    67             //将数组转为逗号分隔的字串
    68             var str = string.Join(",", id);
    69 
    70             //设置Sql语句
    71             var sql = "delete from <#=tbl.Name#> where <#=col.CleanName#> in (" + str + ")";
    72 
    73             //删除
    74             var deleteHelper = new DeleteHelper();
    75             deleteHelper.Delete(sql);
    76         }
    77         #endregion
    78 
    79 <#
    80             }
    81         }
    82 #>
    83     }
    84 
    85 }
    86 
    87 
    88 <# 
    89             // 输出文件结束
    90             manager.EndBlock();
    91         } //if(!ExcludeTables.Contains(tbl.Name)) 判断结束
    92        
    93     }// end foreach
    94 
    95     // 执行编译,生成文件
    96     manager.Process(true);  
    97 #> 
    复制代码

      运行模板,测试看看效果

      

      

      4、同理,我们可以通过判断,生成获取指定名称的字段值和生成删除图片函数等,这些都可以根据你的需要去生成

      

    复制代码
      1 <#@ template debug="false" hostspecific="True" language="C#" #>
      2 <#@ output extension=".cs" encoding="utf-8" #>
      3 <#@ include file="SQLServer.ttinclude" #>
      4 <#@ include file="MultipleOutputHelper.ttinclude"#> 
      5 
      6 <#
      7     //获取所有表与视图
      8     var tables = LoadTables();
      9     //创建多文件生成实体
     10     var manager = Manager.Create(Host, GenerationEnvironment);  
     11 
     12     //遍历所有表
     13     foreach(var tbl in tables){
     14         //判断当前表名是否是禁用名称(禁用的名称可以在Settings.ttinclude文件的ExcludeTables字符串数据中进行添加)
     15         if(!ExcludeTables.Contains(tbl.Name))
     16         {
     17             // 设置输出的文件名
     18             manager.StartNewFile(tbl.ClassName+"Bll.cs");
     19 #> 
     20 using System;
     21 using Solution.DataAccess.DataModel;
     22 using Solution.DataAccess.DbHelper;
     23 
     24 namespace Solution.Logic {
     25 
     26     public partial class <#=tbl.CleanName#>Bll {
     27         
     28         #region 单例模式
     29         //定义单例实体
     30         private static <#=tbl.Name#>Bll _<#=tbl.Name#>Bll = null;
     31 
     32         /// <summary>
     33         /// 获取本逻辑类单例
     34         /// </summary>
     35         /// <returns></returns>
     36         public static <#=tbl.Name#>Bll GetInstence() {
     37             if (_<#=tbl.Name#>Bll == null) {
     38                 _<#=tbl.Name#>Bll = new <#=tbl.Name#>Bll();
     39             }
     40             return _<#=tbl.Name#>Bll;
     41         }
     42         #endregion
     43         
     44 <#
     45         foreach(var col in tbl.Columns){
     46             //判断字段名称中是否包含“_Id”这个字符串,且字段类型为int或long的,则生成对应的删除函数
     47             if (col.CleanName.IndexOf("_Id") >= 0  && (col.SysType == "int" || col.SysType == "long"))
     48             {
     49 #>
     50         #region 删除<#=tbl.Name#>表指定<#=col.CleanName#>的字段值记录
     51         /// <summary>
     52         /// 删除<#=tbl.Name#>表指定<#=col.CleanName#>的字段值记录
     53         /// </summary>
     54         /// <param name="id">记录的主键值</param>
     55         public void DeleteBy<#=col.CleanName#>(int id) {
     56             //删除
     57             <#=tbl.Name#>.Delete(x => x.<#=col.CleanName#> == id);
     58         }
     59 
     60         /// <summary>
     61         /// 删除<#=tbl.Name#>表指定<#=col.CleanName#>的字段值记录
     62         /// </summary>
     63         /// <param name="id">记录的主键值</param>
     64         public void DeleteBy<#=col.CleanName#>(int[] id) {
     65             if (id == null) return;
     66             //将数组转为逗号分隔的字串
     67             var str = string.Join(",", id);
     68 
     69             //设置Sql语句
     70             var sql = "delete from <#=tbl.Name#> where <#=col.CleanName#> in (" + str + ")";
     71 
     72             //删除
     73             var deleteHelper = new DeleteHelper();
     74             deleteHelper.Delete(sql);
     75         }
     76         #endregion
     77 
     78 <#
     79             }
     80             //判断字段名称中是否包含“Name”这个字符串,且字段类型为string
     81             else if (col.CleanName.IndexOf("Name") >= 0 && col.SysType == "string") 
     82             {
     83 #>
     84         #region 获取<#=col.CleanName #>字段值
     85         /// <summary>
     86         /// 获取<#=col.CleanName #>字段值
     87         /// </summary>
     88         /// <param name="pkValue">主键Id</param>
     89         /// <returns></returns>
     90         public string Get<#=col.CleanName #>(int pkValue)
     91         {
     92             //从数据库中查询
     93             var model = <#=tbl.Name#>.SingleOrDefault(x => x.Id == pkValue);
     94             return model == null ? "" : model.<#=col.CleanName #>;            
     95         }
     96         #endregion
     97 
     98 <#
     99             }
    100             //判断字段名称中是否包含“Img”这个字符串,且字段类型为string
    101             else if (col.CleanName.IndexOf("Img") >= 0 && col.SysType == "string") 
    102             {
    103 #>
    104         #region 删除<#=col.CleanName #>字段存储的对应图片
    105         /// <summary>删除<#=col.CleanName #>字段存储的对应图片</summary>
    106         /// <param name="pkValue">主键Id</param>
    107         public void Del<#=col.CleanName #>(int pkValue) {
    108             try {
    109                 //添加删除语句
    110             }
    111             catch (Exception e) {
    112                 //出现异常,保存出错日志信息
    113                 //添加保存出错日志语句
    114             }
    115         }
    116         #endregion
    117 
    118 <#
    119 
    120             }
    121         }
    122 #>
    123     }
    124 
    125 }
    126 
    127 
    128 <# 
    129             // 输出文件结束
    130             manager.EndBlock();
    131         } //if(!ExcludeTables.Contains(tbl.Name)) 判断结束
    132        
    133     }// end foreach
    134 
    135     // 执行编译,生成文件
    136     manager.Process(true);  
    137 #> 
    复制代码

      运行模板,测试看看效果

      

      5、有时候我们会存在一些特殊的需求,有些表或字段要进行过滤操作,这时我们就可以使用一些简单的过滤判断处理

      比如我们对于Manager_Id与Manager_Name这两个字段是不需要生成对应函数的,那么我们就可以加个过滤处理

      首先在Settings.ttinclude文件中创建一个字符串数组变量,并赋值

      

      然后在模板中的循环语句中添加判断

      

      运行模板,测试看看效果

      

      对比第4点的图就可以看到,已经少了两个函数了

      而表名过滤,在上一章节的内容中已经包含了,请看下图

      

      只要在Settings.ttinclude文件中的ExcludeTables变量中添加你想过滤的表名称就可以了

      当然我们还可以写出更多的扩展,这些需要发挥你的想象力,生成更多常用函数,使你从复制粘贴中解放出来,当然函数有变动时,也只需要改一下模板就可以了,方便快捷

      6、对于常用功能来说,前面的生成方式都可以解决,但有时候有些功能直接生成的方式解决不了,那么父类(基类)与虚函数的运用可以帮我们解决很多程序调用的问题。

      比如我们使用IIS缓存,在对记录进行添加、删除与修改操作时,必须同步删除缓存。看到这个需求,可能有的朋友就会说,这很简单啊,直接生成一个缓存删除函数就可以了。是的,这是一种处理方法,但还会存在很多特殊情况,有些时候,我们在自定义函数中也会用到一些缓存,这些缓存并不存在模板中,那么想要模板里的程序在清空模板缓存后,也能自动帮我们清除自定义缓存的话该怎么实现呢?不可能要让我们在相关程序调用的方法中手动添加吧,如果调用的地方太多的话,就很容易忘记了。而我们有一种比较好的解决方式,那就是使用父类(基类),在基类中实现一个删除缓存的虚函数,模板类继承基类后,可以在那些执行添加、删除与修改的函数中直接调用虚函数,而对于这些个性化的删除操作,我们只需要使用override修饰符重写该函数,就可以实现自动删除缓存的功能了。

      具体操作方法请看下面步骤:

      首先创建一个基类

      

      创建一个虚函数

      

      然后再模板中让模板类继承基类,并实现添加、修改与删除方法,在方法中调用删除缓存函数

      

    复制代码
      1 <#@ template debug="false" hostspecific="True" language="C#" #>
      2 <#@ output extension=".cs" encoding="utf-8" #>
      3 <#@ include file="SQLServer.ttinclude" #>
      4 <#@ include file="MultipleOutputHelper.ttinclude"#> 
      5 
      6 <#
      7     //获取所有表与视图
      8     var tables = LoadTables();
      9     //创建多文件生成实体
     10     var manager = Manager.Create(Host, GenerationEnvironment);  
     11 
     12     //遍历所有表
     13     foreach(var tbl in tables){
     14         //判断当前表名是否是禁用名称(禁用的名称可以在Settings.ttinclude文件的ExcludeTables字符串数据中进行添加)
     15         if(!ExcludeTables.Contains(tbl.Name))
     16         {
     17             // 设置输出的文件名
     18             manager.StartNewFile(tbl.ClassName+"Bll.cs");
     19 #> 
     20 using System;
     21 using System.Linq.Expressions;
     22 using Solution.DataAccess.DataModel;
     23 using Solution.DataAccess.DbHelper;
     24 
     25 namespace Solution.Logic 
     26 {
     27 
     28     public partial class <#=tbl.CleanName#>Bll : LogicBase
     29     {
     30         
     31         #region 单例模式
     32         //定义单例实体
     33         private static <#=tbl.Name#>Bll _<#=tbl.Name#>Bll = null;
     34 
     35         /// <summary>
     36         /// 获取本逻辑类单例
     37         /// </summary>
     38         /// <returns></returns>
     39         public static <#=tbl.Name#>Bll GetInstence() 
     40         {
     41             if (_<#=tbl.Name#>Bll == null) 
     42             {
     43                 _<#=tbl.Name#>Bll = new <#=tbl.Name#>Bll();
     44             }
     45             return _<#=tbl.Name#>Bll;
     46         }
     47         #endregion
     48 
     49         #region 添加与编辑<#=tbl.Name#>表记录
     50         /// <summary>
     51         /// 添加与编辑<#=tbl.Name#>记录
     52         /// </summary>
     53         /// <param name="model"><#=tbl.Name#>表实体</param>
     54         public void Save(<#=tbl.Name#> model)
     55         {
     56             try {
     57                 //保存
     58                 model.Save();
     59                 
     60                 //删除缓存
     61                 DelCache();
     62                 
     63                 //添加用户访问记录
     64                 //UseLogBll.GetInstence().Save("{0}" + (model.Id == 0 ? "添加" : "编辑") + "<#=tbl.Name#>记录成功,ID为【" + model.Id + "】");
     65             }
     66             catch (Exception e) {
     67                 //var result = "执行<#=tbl.Name#>Bll.Save()函数出错!";
     68 
     69                 //出现异常,保存出错日志信息
     70                 //CommonBll.WriteLog(result, e, false);
     71             }
     72         }
     73         #endregion
     74 
     75         #region 删除<#=tbl.Name#>表记录
     76         /// <summary>
     77         /// 删除<#=tbl.Name#>表记录
     78         /// </summary>
     79         /// <param name="id">记录的主键值</param>
     80         public void Delete(int id) {
     81             //设置Sql语句
     82             var sql = "delete from <#=tbl.Name#> where Id = " + id;
     83 
     84             //删除
     85             var deleteHelper = new DeleteHelper();
     86             deleteHelper.Delete(sql);
     87             
     88             //删除缓存
     89             DelCache();
     90             
     91             //添加用户操作记录
     92             //UseLogBll.GetInstence().Save("{0}删除了<#=tbl.Name#>表id为【" + id + "】的记录!");
     93         }
     94 
     95         /// <summary>
     96         /// 删除<#=tbl.Name#>表记录
     97         /// </summary>
     98         /// <param name="id">记录的主键值</param>
     99         public void Delete(int[] id) {
    100             if (id == null) return;
    101             //将数组转为逗号分隔的字串
    102             var str = string.Join(",", id);
    103 
    104             //设置Sql语句
    105             var sql = "delete from <#=tbl.Name#> where Id in (" + str + ")";
    106 
    107             //删除
    108             var deleteHelper = new DeleteHelper();
    109             deleteHelper.Delete(sql);
    110             
    111             //删除缓存
    112             DelCache();
    113             
    114             //添加用户操作记录
    115             //UseLogBll.GetInstence().Save("{0}删除了<#=tbl.Name#>表id为【" + str + "】的记录!");
    116         }
    117 
    118         /// <summary>
    119         /// 获取数据表中的某个值——从数据库中查询,如果使用了缓存,删除成功后会清空本表的所有缓存记录,然后重新加载进缓存
    120         /// </summary>
    121         /// <param name="expression">条件语句</param>
    122         /// <returns></returns>
    123         public void Delete(Expression<Func<<#=tbl.Name#>, bool>> expression)
    124         {
    125             //执行删除
    126             <#=tbl.Name#>.Delete(expression);
    127             
    128             //删除缓存
    129             DelCache();
    130             
    131             //添加用户操作记录
    132             //UseLogBll.GetInstence().Save(page, "{0}删除了<#=tbl.Name#>表记录!");
    133         }
    134         #endregion
    135         
    136 <#
    137         foreach(var col in tbl.Columns)
    138         {
    139             //进行过滤判断,指定的字段名称不做处理
    140             if (ExcludeFields.Contains(col.CleanName))
    141                 continue;
    142 
    143             //判断字段名称中是否包含“_Id”这个字符串,且字段类型为int或long的,则生成对应的删除函数
    144             if (col.CleanName.IndexOf("_Id") >= 0  && (col.SysType == "int" || col.SysType == "long"))
    145             {
    146 #>
    147         #region 删除<#=tbl.Name#>表指定<#=col.CleanName#>的字段值记录
    148         /// <summary>
    149         /// 删除<#=tbl.Name#>表指定<#=col.CleanName#>的字段值记录
    150         /// </summary>
    151         /// <param name="id">记录的主键值</param>
    152         public void DeleteBy<#=col.CleanName#>(int id) 
    153         {
    154             //删除
    155             <#=tbl.Name#>.Delete(x => x.<#=col.CleanName#> == id);
    156         }
    157 
    158         /// <summary>
    159         /// 删除<#=tbl.Name#>表指定<#=col.CleanName#>的字段值记录
    160         /// </summary>
    161         /// <param name="id">记录的主键值</param>
    162         public void DeleteBy<#=col.CleanName#>(int[] id) 
    163         {
    164             if (id == null) return;
    165             //将数组转为逗号分隔的字串
    166             var str = string.Join(",", id);
    167 
    168             //设置Sql语句
    169             var sql = "delete from <#=tbl.Name#> where <#=col.CleanName#> in (" + str + ")";
    170 
    171             //删除
    172             var deleteHelper = new DeleteHelper();
    173             deleteHelper.Delete(sql);
    174         }
    175         #endregion
    176 
    177 <#
    178             }
    179             //判断字段名称中是否包含“Name”这个字符串,且字段类型为string
    180             else if (col.CleanName.IndexOf("Name") >= 0 && col.SysType == "string") 
    181             {
    182 #>
    183         #region 获取<#=col.CleanName #>字段值
    184         /// <summary>
    185         /// 获取<#=col.CleanName #>字段值
    186         /// </summary>
    187         /// <param name="pkValue">主键Id</param>
    188         /// <returns></returns>
    189         public string Get<#=col.CleanName #>(int pkValue)
    190         {
    191             //从数据库中查询
    192             var model = <#=tbl.Name#>.SingleOrDefault(x => x.Id == pkValue);
    193             return model == null ? "" : model.<#=col.CleanName #>;            
    194         }
    195         #endregion
    196 
    197 <#
    198             }
    199             //判断字段名称中是否包含“Img”这个字符串,且字段类型为string
    200             else if (col.CleanName.IndexOf("Img") >= 0 && col.SysType == "string") 
    201             {
    202 #>
    203         #region 删除<#=col.CleanName #>字段存储的对应图片
    204         /// <summary>删除<#=col.CleanName #>字段存储的对应图片</summary>
    205         /// <param name="pkValue">主键Id</param>
    206         public void Del<#=col.CleanName #>(int pkValue) 
    207         {
    208             try 
    209             {
    210                 //添加删除语句
    211             }
    212             catch (Exception e) 
    213             {
    214                 //出现异常,保存出错日志信息
    215                 //添加保存出错日志语句
    216             }
    217         }
    218         #endregion
    219 
    220 <#
    221 
    222             }
    223         }
    224 #>
    225     }
    226 
    227 }
    228 
    229 
    230 <# 
    231             // 输出文件结束
    232             manager.EndBlock();
    233         } //if(!ExcludeTables.Contains(tbl.Name)) 判断结束
    234        
    235     }// end foreach
    236 
    237     // 执行编译,生成文件
    238     manager.Process(true);  
    239 #> 
    复制代码

      运行模板,测试看看效果

      

      然后我们创建一个与模版中同名的类

      

      实现虚函数

      

      这样模板函数在执行相关操作时,如果我们重写了清空缓存这个函数,那么程序就会自动执行清空缓存函数了,而对于那些不需要该功能的类则没有任何影响

      这里要注意的是,我们的模板类与这个自定义类都有一个统一的修饰符partial

      大家先消化上面内容,才好理解下一章节中模板调用内容,下章会将写好的模板函数全部贴出来,让大家直接一步到位,生成Web层所需要的绝大部分调用函数,减少这一部分不必要的编码工作。

      

    下载地址:

    T4模板在逻辑层中的应用(二).rar

    版权声明:
      本文由AllEmpty原创并发布于博客园,欢迎转载,未经本人同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。如有问题,可以通过1654937@qq.com 联系我,非常感谢。

      发表本编内容,只要主为了和大家共同学习共同进步,有兴趣的朋友可以加加Q群:327360708 ,大家一起探讨。

      更多内容,敬请观注博客:http://www.cnblogs.com/EmptyFS/

    只有将自己置空,才能装进更多的东西
  • 相关阅读:
    hdu 3074 Multiply game
    uva 10717 Mint
    uva 10128 Queue
    uva 10673 Play with Floor and Ceil
    hdu 1754 I Hate It
    hdu 1166 敌兵布阵
    uva 10079 Pizza Cutting
    费波那列素数
    uva 10236 The Fibonacci Primes
    hdu 1698 Just a Hook
  • 原文地址:https://www.cnblogs.com/FinleyJiang/p/7600793.html
Copyright © 2020-2023  润新知