一個簡單的代碼生成器(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文本模板運用)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM