一个简单的代码生成器(T4文本模板运用)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

说要写这篇文章有一段时间了,但因为最近各方面的压力导致心情十二分的不好,下班后往往都洗洗睡了。今天痛定思痛,终于把这件拖了很久的事做了。好,不废话了,现在看看"一个简单的代码生成器" .


先看看界面吧!

image

简约到如此,说是代码生成器,估计是要被吐槽的。好吧,借用园子里博友的说法,这只是一粒粟子,如果你愿意,你能看到代码生成器的“种子”。

这样运行的!

image

画了个简图已描述这个简单的代码生成器的工作过程。下面的介绍将以此图展开:

1)读取数据表的信息:从数据库中读取数据表的信息并转换成要为T4文本模板引擎提供的数据(EntityClassInfo);

2)将要为T4文本模板引擎提供的数据(EntityClassInfo)作为参数传递给T4文本模板引擎(其实是T4文本模板引擎的宿主,详见T4文本模板转换过程);

3)T4文本模板引擎读取模板;

4)T4文本模板引擎将生成的文本返回给应用程序。

 

代码:

一、在应用程序和代码中传递的参数的类型

1)EntityClassInfo.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
 
namespace EntityInfo
{
    [Serializable]
    public class EntityClassInfo
    {
        public EntityClassInfo(DataTable dt)
        {
            this.ClassName = dt.TableName;
 
            List<EntityClassPropertyInfo> ropertyListTemp = new List<EntityClassPropertyInfo>();
           
            foreach (DataColumn dcol in dt.Columns)
            {
                ropertyListTemp.Add(new EntityClassPropertyInfo(dcol));
            }
            this.RopertyList = ropertyListTemp;
 
            List<EntityClassPropertyInfo> primaryKeyListTemp = new List<EntityClassPropertyInfo>();
            List<EntityClassPropertyInfo> notPrimaryKeyListTemp = new List<EntityClassPropertyInfo>(ropertyListTemp);
            foreach (DataColumn dcol in dt.PrimaryKey)
            {
                primaryKeyListTemp.Add(new EntityClassPropertyInfo(dcol));
                notPrimaryKeyListTemp.Remove(new EntityClassPropertyInfo(dcol));
            }
            this.PrimaryKeyList = primaryKeyListTemp;
            this.NotPrimaryKeyList = notPrimaryKeyListTemp;
        }
        public string ClassName
        {
            get;
            private set;
        }
        public List<EntityClassPropertyInfo> RopertyList
        {
            get;
            private set;
        }
        public List<EntityClassPropertyInfo> PrimaryKeyList
        {
            get;
            private set;
        }
        public List<EntityClassPropertyInfo> NotPrimaryKeyList
        {
            get;
            private set;
        }
    }
}

2)EntityClassPropertyInfo.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
 
namespace EntityInfo
{
    [Serializable]
    public class EntityClassPropertyInfo
    {
        public EntityClassPropertyInfo(DataColumn dcol)
        {
            this.PropertyName = dcol.ColumnName;
            this.PropertyType = dcol.DataType.Name;
            this.IsValueType = false;
            if (dcol.DataType.IsValueType)
            {
                if (dcol.AllowDBNull)
                {
                    this.PropertyType = this.PropertyType + "?";
                }
                else
                {
                    this.IsValueType = true;
                }
            }
        }
 
        public string PropertyName
        {
            get;
            private set;
        }
 
        public string PropertyType
        {
            get;
            private set;
        }
 
        public bool IsValueType
        {
            get;
            private set;
        }
 
        public override bool Equals(object obj)
        {
            EntityClassPropertyInfo temp = obj as EntityClassPropertyInfo;
            if (this.PropertyName == temp.PropertyName && this.PropertyType == temp.PropertyType)
            {
                return true;
            }
            return false;
        }
        
    }
}

二、模板

1)生成实体类的模板:Entity.tt

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".txt" #>
<#@ import namespace="EntityInfo" #>
<#@ parameter type="EntityInfo.EntityClassInfo" name="entity" #>
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
 
/// <summary>
/// <#= entity.ClassName#> 的摘要说明
/// </summary>
public class <#= entity.ClassName#>
{
    public <#= entity.ClassName#>()
    {
            //
            // TODO: 在此处添加构造函数逻辑
            //
    }
<#  foreach(EntityClassPropertyInfo property in entity.RopertyList)
    { #>
    private <#= property.PropertyType#> m_<#= property.PropertyName#>;
<#;
     }
#>
 
<#  foreach(EntityClassPropertyInfo property in entity.RopertyList)
    { #>
    public  <#= property.PropertyType#>  <#= property.PropertyName#>
    {
        set { m_<#= property.PropertyName#> = value; }
        get { return m_<#= property.PropertyName#>; }
    }
<#;
    }
#>
 
}

2)生成DAL层的模板:DataAccess.tt

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".txt" #>
<#@ import namespace="EntityInfo" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ parameter type="EntityInfo.EntityClassInfo" name="entity" #>
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using MySql.Data.MySqlClient;
using System.Collections.Generic;
 
/// <summary>
/// <#= entity.ClassName#> 的摘要说明
/// </summary>
public class <#= entity.ClassName#>DAL
{
    public <#= entity.ClassName#>DAL()
    {
 
    }
 
    #region 私有方法
 
    #region 根据实体类获取MySqlParameter数组 +MySqlParameter[] FromModel(<#= entity.ClassName#> model)
    private static MySqlParameter[] FromModel(<#= entity.ClassName#> model)
    {
        List<MySqlParameter> parameterList = new List<MySqlParameter>();
<#  foreach(EntityClassPropertyInfo property in entity.RopertyList)
    { 
#>        parameterList.Add(new MySqlParameter("@<#=property.PropertyName#>", SQLHelper.ToDBValue(model.<#=property.PropertyName#>)));
<#; 
    }
#>
        return parameterList.ToArray();
    }
    #endregion
 
 
    #region 将dr中的数据转换为实体类对象 + <#= entity.ClassName#> ToModel(DataRow dr)
    private static <#= entity.ClassName#> ToModel(DataRow dr)
    {
        <#= entity.ClassName#> model = new <#= entity.ClassName#>();
<#  foreach(EntityClassPropertyInfo property in entity.RopertyList)
    { 
        if(property.IsValueType)
        {
#>        model.<#=property.PropertyName#> = Convert.To<#= property.PropertyType#>(SQLHelper.FromDBValue(dr["<#= property.PropertyName #>"]));
<#;
        }
        else
        {
#>        model.<#=property.PropertyName#> = SQLHelper.FromDBValue(dr["<#=property.PropertyName#>"]) as <#=property.PropertyType#>;
<#;
        }
    }
#>
        return model;
    }
    #endregion
 
    #endregion
 
    #region 增 + int Insert(<#= entity.ClassName#> model)
    public static int Insert(<#= entity.ClassName#> model)
    {
        int result = -1;
        string sql = @"INSERT INTO <#= entity.ClassName#>(<#= string.Join(",",GetSqlInsertInto()) #>) 
                VALUES(<#= string.Join(",",GetSqlInsertValue()) #>);";
        
        result = SQLHelper.ExecuteNonQuery(sql,FromModel(model));
       
        return result;
    }
    #endregion
 
    #region 删 + int DeleteById(<#= string.Join(",",GetSqlDelVariable()) #>)
    public static int DeleteById(<#= string.Join(",",GetSqlDelVariable()) #>)
    {
        int result = -1;
        string sql = @"DELETE FROM <#= entity.ClassName#> WHERE <#= string.Join(" AND ",GetSqlWhereId()) #>;";
 
        result = SQLHelper.ExecuteNonQuery(sql,<#= string.Join(",",GetSqlDelParameter()) #>);
        
        return result;
    }
    #endregion
    
    #region 改 + int Update(<#= entity.ClassName#> model)
    public static int Update(<#= entity.ClassName#> model)
    {
        int result = -1;
        string sql = @"UPDATE <#= entity.ClassName#> 
                     SET <#= string.Join(",",GetSqlUpdateSet()) #>
                     WHERE <#= string.Join(" AND ",GetSqlWhereId()) #>";
        
        result = SQLHelper.ExecuteNonQuery(sql, FromModel(model));
       
        return result;
    }
    #endregion
    
    #region 查 + int GetCountAll()
    public static int GetCountAll()
    {
        int result = 0;
        string sql = @"SELECT Count(*) FROM <#= entity.ClassName#>;";
 
        result = Convert.ToInt32(SQLHelper.ExecuteScalar(sql));
       
        return result;
    }
    #endregion
 
    #region 查 + List<<#= entity.ClassName#>> GetBySql(string sql,params MySqlParameter[] parameters)
    public static List<<#= entity.ClassName#>> GetBySql(string sql,params MySqlParameter[] parameters)
    {
        List<<#= entity.ClassName#>> modelList = new List<<#= entity.ClassName#>>();
        DataTable dt = SQLHelper.ExecuteDataTable(sql,parameters);
        
        foreach (DataRow dr in dt.Rows)
        {
            modelList.Add(ToModel(dr));
        }
        return modelList;
    }
    #endregion
}
 
<#+
    private string[] GetSqlInsertInto()
    {
        List<string> propertyNameList= new List<string>();
        foreach(EntityClassPropertyInfo property in entity.RopertyList)
        {
            propertyNameList.Add(property.PropertyName);
        }
        return propertyNameList.ToArray();
    }
    private string[] GetSqlInsertValue()
    {
        List<string> propertyNameList= new List<string>();
        foreach(EntityClassPropertyInfo property in entity.RopertyList)
        {
            propertyNameList.Add("@" + property.PropertyName);
        }
        return propertyNameList.ToArray();
    }
    private string[] GetSqlDelVariable()
    {
        List<string> propertyList= new List<string>();
        foreach(EntityClassPropertyInfo property in entity.PrimaryKeyList)
        {
            propertyList.Add(property.PropertyType + "  m_" + property.PropertyName);
        }
        return propertyList.ToArray();
    }
    private string[] GetSqlDelParameter()
    {
        List<string> propertyList= new List<string>();
        foreach(EntityClassPropertyInfo property in entity.PrimaryKeyList)
        {
            propertyList.Add("new MySqlParameter(@\"" + property.PropertyName + "\" ,m_" + property.PropertyName + ")");
        }
        return propertyList.ToArray();
    }
 
    private string[] GetSqlUpdateSet()
    {
        List<string> propertyList= new List<string>();
        foreach(EntityClassPropertyInfo property in entity.NotPrimaryKeyList)
        {
            propertyList.Add(property.PropertyName +"=@" + property.PropertyName);
        }
        return propertyList.ToArray();
    }
    private string[] GetSqlWhereId()
    {
        List<string> propertyList= new List<string>();
        foreach(EntityClassPropertyInfo property in entity.PrimaryKeyList)
        {
            propertyList.Add(property.PropertyName +"=@" + property.PropertyName);
        }
        return propertyList.ToArray();
    }
   
 #>

三、代码生成四步走:

1)从数据表信息 =》EntityClassInfo:

DataTable dt = SQLHelper.ExecuteDataTable(SQLHelper.GetConnectionString(), string.Format("SELECT * FROM {0} LIMIT 0,0", cbbTableName.SelectedValue.ToString()));
EntityClassInfo entityInfo = new EntityClassInfo(dt);

备注:

#region ExecuteTable方法
        public static DataTable ExecuteDataTable(string connectionString,string sql, params MySqlParameter[] parameters)
        {
            using (MySqlConnection conn = new MySqlConnection(connectionString))
            { 
                using(MySqlCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sql;
                    cmd.Parameters.AddRange(parameters);
                    using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
                    {
                        using (DataTable dt = new DataTable())
                        {
                            da.Fill(dt);
                            da.FillSchema(dt, SchemaType.Source);   //从数据源中检索架构
                            return dt;
                        }
                    }
                }
            }
        }
        #endregion

2)给T4文本模板传参:

CustomTextTemplatingEngineHost host = new CustomTextTemplatingEngineHost();
host.Session = new TextTemplatingSession();
host.Session.Add("entity", classInfo);

3)读取文本模板:

string input = File.ReadAllText(templatePath);
string output = new Engine().ProcessTemplate(input, host);

4)返回生成的文本:

string output = new Engine().ProcessTemplate(input, host);

源码下载(VS2010项目):一个简单的代码生成器(T4文本模板运用)

作者: 韩兆新
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
分类:  [11]我的开源
标签:  T4文本模板

本文转自韩兆新博客博客园博客,原文链接:http://www.cnblogs.com/hanzhaoxin/p/3815410.html,如需转载请自行联系原作者
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
4月前
|
存储 编译器 C++
【C++】什么是模板?怎样使用模板?
【C++】什么是模板?怎样使用模板?
37 0
Revit二次开发—创建文字注释(TextNote)
Revit二次开发—创建文字注释(TextNote)
|
C# 文件存储 数据库
CodeSmith 二、多模板按目录树批量自动生成代码(下1)
通过调用指定目录下的所有模板,逐一按照数据表生成独立的代码文件。支持多模板调用、支持所有数据表生成或批量指定多个生成、支持自动的文件目录结构、支持代码文件格式化命名等。
180 0
CodeSmith 二、多模板按目录树批量自动生成代码(下1)
六石风格文档范例:做测试结果表格
六石风格文档范例:做测试结果表格
60 0
六石风格文档范例:做测试结果表格
|
XML 数据格式
使用freemarker模板导出word文档
使用freemarker模板导出word文档
399 0
使用freemarker模板导出word文档
|
Dubbo Java 应用服务中间件
DocView 现在支持自定义 Markdown 模版了!
有小伙伴反馈说希望可以自定义 Markdown 模版,这样就可以导出自己想要的样式了!这个功能可以有,毕竟大家不可能都生成一模一样的文档。现在来一起看看如何实现自定义模版吧!
80 0
|
Java 数据库
FreeMarker 模板来定义字符串模板
FreeMarker 模板来定义字符串模板
309 0
FreeMarker 模板来定义字符串模板
|
关系型数据库 MySQL 数据库
CodeSmith 二、多模板按目录树批量自动生成代码(上)
通过调用指定目录下的所有模板,逐一按照数据表生成独立的代码文件。支持多模板调用、支持所有数据表生成或批量指定多个生成、支持自动的文件目录结构、支持代码文件格式化命名等。
98 0
CodeSmith 二、多模板按目录树批量自动生成代码(上)
|
Web App开发 XML 数据格式