Fork me on GitHub

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

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


先看看界面吧!

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文本模板运用)

posted @ 2014-06-29 18:59  韩兆新  阅读(6105)  评论(0编辑  收藏  举报