分享改進 完全定制自己的代碼生成器
2015-03-12 09:51 熬夜的蟲子 閱讀(4328) 評論(15) 收藏 舉報codesmith確實是款不錯的工具 但是它并不開源 對于一些有自己特殊需求的用戶只能自己另想其他解決方案 例如我說想做一個web版本的代碼生成器或者說用戶沒有c#基礎
這里開源一個之前做過的工具 當初的目的主要是解決在框架當中局部更新的問題
因為在大部分orm框架當中都是簡單的獲取一個實體 然后這個實體某個值 然后更新的時候 還是傳入這個改變的實體 不過嚴格意義上來說 在你傳入更新實體的時候 它的其他字段說不定已經被其他請求更新過了 所以導致你的這次更新會覆蓋掉別人的更新 當然也會有同一字段的問題 不過這里不深入討論該問題 重點在代碼生成上
另外一個意義 就是讓大家了解一下一般的代碼生成器的工作流程以及實現方法
Github地址 https://github.com/dubing/CodePorter

使用方法很簡單 先輸入數據庫連接字符串 下面會出現table和view,當然自己可以根據源代碼加載更多的內容

我程序里主要生成實體層和數據處理層所以我提供了2個文本框 一個是實體層的命名空間 一個是數據處理層的命名的命名空間,這樣就不用在模板里設置,可以在win界面或者web界面直接修改
選擇好表和view并且設置好命名空間后點擊啟動 左下角提示成功后就可以打開目錄 查看自己生成的文件

生成的實體文件

這里的PartiallyColumnAttribute主要就是用來解決局部更新問題,和代碼生成本身無關聯。
DA文件
//------------------------------------
//用途:表LitespeedActivity的數據處理類(工具自動生成)
//作者:杜兵
//時間:2015-03-11 05:43:32
//-------------------------------------
using System;
using System.Data;
using System.Data.Common;
using Model.Service;
using Ctrip.TMPay.Framework.Common;
using Ctrip.TMPay.DataAccess.Common;
namespace DataAccess.Service
{
public partial class LitespeedActivityDA : BaseDA<LitespeedActivityDA>
{
/// <summary>
/// 根據主鍵獲取LitespeedActivity
///</summary>
///< param name="serverName"></param>
///< returns></returns>
public LitespeedActivityEntity GetLitespeedActivity(String serverName)
{
DbCommand dbCmd = DbObject.GetSqlStringCommand(SqlCommandConstants.LitespeedActivitySelectCommand);
DbObject.AddInParameter(dbCmd, "@ServerName", DbType.String, serverName);
LitespeedActivityEntity litespeedActivityEntity = null;
using (IDataReader dataReader = DbObject.ExecuteReader(dbCmd))
{
if (dataReader.Read())
{
litespeedActivityEntity = new LitespeedActivityEntity{
ServerName = DbFieldHelper.GetString(dataReader, "ServerName"),
ActivityID = DbFieldHelper.GetInt32(dataReader, "ActivityID"),
DatabaseID = DbFieldHelper.GetInt32(dataReader, "DatabaseID"),
ActivityTypeID = DbFieldHelper.GetInt32(dataReader, "ActivityTypeID"),
StartTime = DbFieldHelper.GetDateTime(dataReader, "StartTime"),
FinishTime = DbFieldHelper.GetDateTime(dataReader, "FinishTime"),
StatusTypeID = DbFieldHelper.GetInt32(dataReader, "StatusTypeID"),
DatabaseSize = DbFieldHelper.GetDouble(dataReader, "DatabaseSize"),
PercentCompleted = DbFieldHelper.GetInt32(dataReader, "PercentCompleted"),
ActivityDetail = DbFieldHelper.GetString(dataReader, "ActivityDetail"),
ErrorMessage = DbFieldHelper.GetString(dataReader, "ErrorMessage"),
ResultMessage = DbFieldHelper.GetString(dataReader, "ResultMessage"),
ReplicateID = DbFieldHelper.GetGuid(dataReader, "ReplicateID"),
LS = DbFieldHelper.GetByte(dataReader, "LS"),
PID = DbFieldHelper.GetInt32(dataReader, "PID"),
NativeSize = DbFieldHelper.GetDouble(dataReader, "NativeSize"),
BackupSize = DbFieldHelper.GetDouble(dataReader, "BackupSize"),
BackupTime = DbFieldHelper.GetDouble(dataReader, "BackupTime"),
AttachedNativeSize = DbFieldHelper.GetDouble(dataReader, "AttachedNativeSize"),
AttachedBackupSize = DbFieldHelper.GetDouble(dataReader, "AttachedBackupSize"),
AttachedBackupTime = DbFieldHelper.GetDouble(dataReader, "AttachedBackupTime"),
};
}
}
return litespeedActivityEntity;
}
/// <summary>
/// 根據主鍵獲取LitespeedActivity
///</summary>
///< param name="activityID"></param>
///< returns></returns>
public LitespeedActivityEntity GetLitespeedActivity(Int32 activityID)
{
DbCommand dbCmd = DbObject.GetSqlStringCommand(SqlCommandConstants.LitespeedActivitySelectCommand);
DbObject.AddInParameter(dbCmd, "@ActivityID", DbType.Int32, activityID);
LitespeedActivityEntity litespeedActivityEntity = null;
using (IDataReader dataReader = DbObject.ExecuteReader(dbCmd))
{
if (dataReader.Read())
{
litespeedActivityEntity = new LitespeedActivityEntity{
ServerName = DbFieldHelper.GetString(dataReader, "ServerName"),
ActivityID = DbFieldHelper.GetInt32(dataReader, "ActivityID"),
DatabaseID = DbFieldHelper.GetInt32(dataReader, "DatabaseID"),
ActivityTypeID = DbFieldHelper.GetInt32(dataReader, "ActivityTypeID"),
StartTime = DbFieldHelper.GetDateTime(dataReader, "StartTime"),
FinishTime = DbFieldHelper.GetDateTime(dataReader, "FinishTime"),
StatusTypeID = DbFieldHelper.GetInt32(dataReader, "StatusTypeID"),
DatabaseSize = DbFieldHelper.GetDouble(dataReader, "DatabaseSize"),
PercentCompleted = DbFieldHelper.GetInt32(dataReader, "PercentCompleted"),
ActivityDetail = DbFieldHelper.GetString(dataReader, "ActivityDetail"),
ErrorMessage = DbFieldHelper.GetString(dataReader, "ErrorMessage"),
ResultMessage = DbFieldHelper.GetString(dataReader, "ResultMessage"),
ReplicateID = DbFieldHelper.GetGuid(dataReader, "ReplicateID"),
LS = DbFieldHelper.GetByte(dataReader, "LS"),
PID = DbFieldHelper.GetInt32(dataReader, "PID"),
NativeSize = DbFieldHelper.GetDouble(dataReader, "NativeSize"),
BackupSize = DbFieldHelper.GetDouble(dataReader, "BackupSize"),
BackupTime = DbFieldHelper.GetDouble(dataReader, "BackupTime"),
AttachedNativeSize = DbFieldHelper.GetDouble(dataReader, "AttachedNativeSize"),
AttachedBackupSize = DbFieldHelper.GetDouble(dataReader, "AttachedBackupSize"),
AttachedBackupTime = DbFieldHelper.GetDouble(dataReader, "AttachedBackupTime"),
};
}
}
return litespeedActivityEntity;
}
/// <summary>
/// 全參數更新LitespeedActivity
///</summary>
///< param name="litespeedActivityEntity">LitespeedActivityEntity</param>
///< returns></returns>
public BizResult<string> UpdateLitespeedActivity(LitespeedActivityEntity litespeedActivityEntity)
{
FillParams(litespeedActivityEntity);
return PartiallyUpdateLitespeedActivity(litespeedActivityEntity);
}
/// <summary>
/// 部分參數更新LitespeedActivity
///</summary>
///< param name="litespeedActivityEntity">LitespeedActivityEntity</param>
///< returns></returns>
public BizResult<string> PartiallyUpdateLitespeedActivity(LitespeedActivityEntity litespeedActivityEntity)
{
return ExecuteSP(SqlProcedureConstants.LitespeedActivityUpdateSpName, CheckUpdate, litespeedActivityEntity);
}
/// <summary>
/// 創建LitespeedActivity
///</summary>
///< param name="litespeedActivityEntity">LitespeedActivityEntity</param>
///< returns></returns>
public BizResult<string> CreateLitespeedActivity(LitespeedActivityEntity litespeedActivityEntity)
{
FillParams(litespeedActivityEntity);
return ExecuteSP(SqlProcedureConstants.LitespeedActivityInsertSpName, null, litespeedActivityEntity);
}
/// <summary>
/// 刪除LitespeedActivity
///</summary>
///< param name="litespeedActivityEntity">LitespeedActivityEntity</param>
///< returns></returns>
public BizResult<string> DeleteLitespeedActivity(LitespeedActivityEntity litespeedActivityEntity)
{
FillPKParams(litespeedActivityEntity);
return ExecuteSP(SqlProcedureConstants.LitespeedActivityDeleteSpName, null, litespeedActivityEntity);
}
}
}
還有其他的一些文件就不一一列出了
原理很簡單 也是根據模板。不過和codesmith不同的是 我這里用的是xsl模板包括語法

基于xml的語法并不難 就算不懂.net的人學習半個小時也可以自己定制模板了
舉個例子
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding="utf-8" method="text" indent="no"/> <xsl:variable name="BaseName" select="/DocumentElement/@BaseName"/> <xsl:variable name="BaseDbObject" select="/DocumentElement/@BaseDbObject"/> <xsl:variable name="DefaultNamespace" select="/DocumentElement/@DefaultNamespace"/> <xsl:variable name="DateTime" select="/DocumentElement/@DateTime"/> <xsl:variable name="SchemaTable" select="/DocumentElement/SchemaTable[translate(IsHidden,'TRUE','true')!='true']"/> <xsl:variable name="TableClassName"> <xsl:value-of select="$BaseName"/>Table </xsl:variable> <xsl:template match="/"> //------------------------------------ //用途:表<xsl:value-of select="$BaseDbObject"/>的實體類(工具自動生成) //作者:杜兵 //時間:<xsl:value-of select="$DateTime"/> //------------------------------------- using System; using System.Data; namespace <xsl:value-of select="$DefaultNamespace"/> { [Serializable] public partial class <xsl:value-of select="$BaseName"/>Entity : BaseEntity {<xsl:for-each select="$SchemaTable"> <xsl:variable name="PublicPropertyName"> <xsl:value-of select="PropertyName"/> </xsl:variable> <xsl:variable name="ShortDataType"> <xsl:choose> <xsl:when test="ProviderDataType='System.Data.SqlTypes.SqlXml'">System.Xml.Linq.XElement</xsl:when> <xsl:otherwise> <xsl:value-of select="ShortDataType"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="DbDataType"> <xsl:choose> <xsl:when test="ProviderTypeName='SqlDbType.Timestamp'">rowversion</xsl:when> <xsl:when test="ProviderTypeName='SqlDbType.Variant'">Variant</xsl:when> <xsl:otherwise> <xsl:value-of select="DataTypeFullName"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="Description"> <xsl:value-of select="Description"/> </xsl:variable><xsl:variable name="DbType"> <xsl:value-of select="DBDataTypeFullName"/> </xsl:variable> /// <summary> /// <xsl:value-of select="$Description"/> ///</summary> [PartiallyColumnAttribute(DbType = <xsl:value-of select="$DbType"/> <xsl:choose><xsl:when test="AllowDBNull='false'">, CanBeNull = false</xsl:when><xsl:otherwise>, CanBeNull = true</xsl:otherwise></xsl:choose><xsl:if test="IsKey='true'">, IsPrimaryKey = true</xsl:if>)] public <xsl:value-of select="$ShortDataType"/><xsl:text> </xsl:text><xsl:value-of select="$PublicPropertyName"/> { get; set; }</xsl:for-each> } } </xsl:template> </xsl:stylesheet>
這里代碼里模板實現主要是解決局部更新的功能,大家可以根據自己不同的需求來修改部分邏輯。
核心的配置文件在config下CodeSet.xml
主要的配置節點如下
<generatorSettings> <ConstantsGenerator> <add key="DataSourceType" value="CodePorter.Core.DbTableSource"/> <add key="XslTemplate" value="CodePorter.Templates.SqlConstantsTemplate.xsl"/> <add key="TargetFile" value=".\Repository\SqlConstants.cs"/> <add key="BeginRegion" value="#region select command,#region sp name"/> <add key="EndRegion" value="#endregion,#endregion"/> </ConstantsGenerator> <BaseDbEntityGenerator> <add key="DataSourceType" value="CodePorter.Core.DbTableSource"/> <add key="XslTemplate" value="CodePorter.Templates.BaseDbEntityTemplate.xsl"/> <add key="TargetFile" value=".\Entity\BaseEntity.cs"/> </BaseDbEntityGenerator> <DbEntityGenerator> <add key="DataSourceType" value="CodePorter.Core.DbTableSource"/> <add key="XslTemplate" value="CodePorter.Templates.DbEntityTemplate.xsl"/> <add key="TargetFile" value=".\Entity\%BASENAME%Entity.cs"/> </DbEntityGenerator> <BaseDAGenerator> <add key="DataSourceType" value="CodePorter.Core.DbTableSource"/> <add key="XslTemplate" value="CodePorter.Templates.BaseDATemplate.xsl"/> <add key="TargetFile" value=".\Repository\BaseDA.cs"/> </BaseDAGenerator> <DAGenerator> <add key="DataSourceType" value="CodePorter.Core.DbTableSource"/> <add key="XslTemplate" value="CodePorter.Templates.DATemplate.xsl"/> <add key="TargetFile" value=".\Repository\%BASENAME%DA.cs"/> </DAGenerator> </generatorSettings>
細節比較多,但是通過源代碼大家應該理解都沒有問題,如果有不清楚的地方可以給我留言。后續會放出更多以前做過的工具。
希望對大家有幫助。
![]() |
原創作品允許轉載,轉載時請務必以超鏈接形式標明文章原始出處以及作者信息。 作者:熬夜的蟲子 點擊查看:博文索引 |

浙公網安備 33010602011771號