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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

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


先看看界面吧!

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,如需转载请自行联系原作者
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
C#有关字符串的分割,替换,截取
C#有关字符串的分割,替换,截取
|
C# C++
创建目标类型对象在C#7.3中不可用,请使用9.0或更高的语言版本
创建目标类型对象在C#7.3中不可用,请使用9.0或更高的语言版本
2468 0
创建目标类型对象在C#7.3中不可用,请使用9.0或更高的语言版本
|
XML 缓存 前端开发
Thymeleaf一篇就够了
Thymeleaf是Springboot官方支持的模板引擎,有着动静分离等独有特点,通过本文简单学习下吧!
62252 24
Thymeleaf一篇就够了
|
Java 数据库
POJO、PO、DTO、DAO、BO、VO需要搞清楚的概念
POJO 全称为:Plain Ordinary Java Object,即简单普通的java对象。一般用在数据层映射到数据库表的类,类的属性与表字段一一对应。 PO 全称为:Persistant Object,即持久化对象。
33217 1
|
存储 JavaScript 前端开发
细读 Git | 让你弄懂 origin、HEAD、FETCH_HEAD 相关内容
细读 Git | 让你弄懂 origin、HEAD、FETCH_HEAD 相关内容
5242 2
细读 Git | 让你弄懂 origin、HEAD、FETCH_HEAD 相关内容
|
7月前
|
存储 Shell 开发工具
Git和TortoiseGit的安装与使用
Git和TortoiseGit的结合使用,可以大大提高版本控制的效率和便捷性。通过本文的步骤,您可以轻松安装和配置Git及TortoiseGit,并掌握基本的版本控制操作。
1430 82
|
安全 Java 应用服务中间件
当遇到非法 URL 参数时,如何保障网页正常打开
访问如`http://example.com?a@b=1`的链接出现400 Bad Request错误,这是因为Tomcat不允许请求目标中含有非法字符。Spring Boot 2可通过配置`server.tomcat.relaxed-query-chars`来允许特殊字符,但这样做可能引入安全风险。因此,建议在Nginx层使用`rewrite_by_lua_block`和`ngx.redirect`进行重定向,将非法字符替换为合法形式,如`http://example.com?ab=1`,同时记录日志以监控。此方案能避免直接修改后端代码,提高安全性。
565 0
|
11月前
|
搜索推荐 Java UED
SpringBoot 自定义启动画面:打造个性化应用启动体验
【10月更文挑战第7天】在软件开发中,细节往往能够体现一个团队的专业性和对用户体验的关注。SpringBoot作为快速构建Spring应用的框架,其简洁的启动流程和强大的功能深受开发者喜爱。然而,默认的启动画面可能略显单调,无法充分展示应用的特色或品牌。本文将详细介绍如何为SpringBoot应用自定义启动画面,让应用在启动时就能给人留下深刻印象。
297 1
|
测试技术 API 开发者
.NET单元测试框架大比拼:MSTest、xUnit与NUnit的实战较量与选择指南
【8月更文挑战第28天】单元测试是软件开发中不可或缺的一环,它能够确保代码的质量和稳定性。在.NET生态系统中,MSTest、xUnit和NUnit是最为流行的单元测试框架。本文将对这三种测试框架进行全面解析,并通过示例代码展示它们的基本用法和特点。
1313 8
|
JavaScript 前端开发 API
尤雨溪分享 Vue.js 10 年的发展历程,谈谈我看完后的启发和感受!!
尤雨溪分享 Vue.js 10 年的发展历程,谈谈我看完后的启发和感受!!