一、简介

开源代码生成器-Kalman Studio

https://github.com/loamen/Kalman.Studio

T4学习- 2、T4代码生成器-Kalman Studio

1、软件主要功能如下:

1、基于T4的代码生成工具,根据数据库元数据信息生成代码,支持多数据库,支持批量代码生成;
2、支持根据PowerDesigner物理模型文件来生成代码;
3、内置了一个简单的文本编辑器,支持代码高亮显示;
4、数据库元数据信息浏览工具;
5、数据库文档生成工具,支持输出word及pdf文件格式;
6、IIS日志解析器,小网站可以用用;
7、其他工具,字符串相关操作等。

二、编写T4模板:

1、VS自动根据模板自动生成代码

首先,打开Visual Studio,新建一个文本文件,将扩展名改为"tt"
T4学习- 2、T4代码生成器-Kalman Studio

这时Visual Studio会为Entity.tt生成一个对应的类文件Entity.cs。这是因为Visual Studio内置了一个代码生成工具“TextTemplatingFileGenerator”,会自动为每个模板文件生成对应的类文件,如果你在Entity.tt中编辑好模板,然后打开Entity.cs,TextTemplatingFileGenerator会自动解析模板,将代码输出到文件Entity.cs。

T4学习- 2、T4代码生成器-Kalman Studio

2、编写T4模板

我们这里不需要使用TextTemplatingFileGenerator生成代码,把属性面板,“自定义工具”里面的文字“TextTemplatingFileGenerator”删掉,对应的类文件会自动删除;然后可以开始编写模板了。

我这里先展示一个编写好的实体模板,然后再详细说明。

<#@ template language="C#v3.5" hostSpecific="true" debug="true" #>
<#@ output extension=".cs" #>
<# 
    TableHost host = (TableHost)(Host); 
    SOTable table = host.Table;
    List<SOColumn> list = host.ColumnList;
    string columnPrefix = host.GetString("ColumnPrefix");
    int prefixLevel = host.GetInt32("PrefixLevel");
    string nameSpace = host.GetString("NameSpace");
    string className = host.GetString("ClassName");
    if(string.IsNullOrEmpty(nameSpace))nameSpace = "Entity";
    if(string.IsNullOrEmpty(className))className = table.Name;
#>
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace <#= nameSpace #>
{
    /// <summary>
    /// <#= table.Comment == "" ? table.Name : table.Comment #>
    /// </summary>
    [Serializable]
    public partial class <#= className #>
    {
        <# foreach (SOColumn c in list)
        { #>/// <summary>
        /// <#= c.Comment == "" ? c.Name : c.Comment #>
        /// </summary>
        public <#= TypeUtil.DbType2TypeString(c.DataType) #> <#= StringUtil.RemovePrefix(c.Name, columnPrefix, prefixLevel).Replace(" ", "") #> { get; set; }
        
        <# } #>
        
    }
}

3、T4模板语法

  • <#@ template language="C#v3.5" hostSpecific="true" debug="true" #>:可以指定模板使用的语言,hostSpecific="true"表示是否使用特定的host(Kalman Studio里面使用的是TableHost对象,必须实现接口ITextTemplatingEngineHost)。
  • <#@ output extension=".cs" #> : 指定生成文件的扩展名。
  • <#@ assembly name="System.Data" #>:添加程序集引用,如果要使用第三方程序集,那么最好在项目中添加引用,或者加入到GAC。
  • <#@ import namespace="System.Data" #>:导入要使用的命名空间,注意:这里的命名空间必须要在前面指定的程序集里面找得到的,比如我指定命名空间"System.Data","System.Data.Common",这些在程序集System.Data中都有的。
  • <#@ include file="test.tt" #> 导入模板,类似Html的include用法
  • <#   #>:定义代码块
  • <#= #>:定义表达式
  • <#+ #>:定义变量

三、Kalman Studio改进

1、自定义架构对象SchemaObject下的类。

T4学习- 2、T4代码生成器-Kalman Studio

2、自定义T4模板的引擎主机类:T4TemplatingEngineHost

T4学习- 2、T4代码生成器-Kalman Studio

3、自定义SqlServerSchema

T4学习- 2、T4代码生成器-Kalman Studio

更改Kalman项目的SqlServerSchema文件,增加Computed是否是计算字段的判断。

T4学习- 2、T4代码生成器-Kalman Studio
 public override List<SOColumn> GetTableColumnList(SOTable table)
        {
            string cmdText = string.Format(@"use [{2}];select   colm.name column_name, object_definition(colm.default_object_id) as column_def, systype.name type_name, colm.is_identity, colm.is_nullable ,
                                                        cast(colm.max_length as int) length, cast(colm.precision as int) precision, cast(colm.scale as int) scale, colm.is_computed
                                            from     sys.columns colm
                                                inner join sys.types systype on colm.system_type_id = systype.system_type_id and colm.user_type_id = systype.user_type_id
                                            where    colm.object_id = object_id('{0}')
                                            order by colm.column_id;", table.Name, table.Owner, table.Database.Name);

            List<SOColumn> columnList = new List<SOColumn>();
            List<string> pkList = GetPrimaryKeys(table);
            DataTable dt = this.DbProvider.ExecuteDataSet(System.Data.CommandType.Text, cmdText).Tables[0];

            foreach (DataRow row in dt.Rows)
            {
                SOColumn column = new SOColumn
                {
                    Parent = table,
                    Name = row["column_name"].ToString(),
                    DefaultValue = row["column_def"].ToString(),
                    Nullable = row["is_nullable"].ToString()== "True",
                    NativeType = row["type_name"].ToString(),
                    Identify = row["is_identity"].ToString() == "True",
                    Computed = row["is_computed"].ToString() == "True",
                    //ForeignKey
                    Length = ConvertUtil.ToInt32(row["length"], -1),
                    Precision = ConvertUtil.ToInt32(row["precision"], -1),
                    Scale = ConvertUtil.ToInt32(row["scale"], –1),
                };

                column.PrimaryKey = pkList.Contains(column.Name);
                column.DataType = this.GetDbType(column.NativeType);
                column.Comment = GetColumnComment(column);
                columnList.Add(column);
            }

            return columnList;
        }
View Code

相关文章: