多年前用过李天平前辈的,自己改过,后来李老师做动软了,不给源码,修改不是很方便。加上我目前需要转java方向,于是决定自己搞。到目前为止花了整整一个星期了,看看目前的成果。
最后是代码工程文件,用c#开发的,IDE是vs2010
为了实现最大的模板自由,设计了专有的模板语法。基于C#,但是已经做到尽量简化,对有一点开发经验的同行应该是很好上手的。
目前c#的代码模板已经做了一些通用样例,接下来做java的开发代码模板。
总之,为了提高效率,并且规范项目团队成员的代码书写。
下面把核心的代码两个类文件贴出来,分别是动态编译和模板解析
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.CodeDom.Compiler; 6 using System.Reflection; 7 8 namespace CodeMaker.Engine 9 { 10 public class Compiler 11 { 12 /// <summary> 13 /// 普通代码编译执行出字符串 14 /// </summary> 15 /// <param name="strCode"></param> 16 /// <returns></returns> 17 public static string DoCompile(string strCode) 18 { 19 20 StringBuilder strResults = new StringBuilder(); 21 22 CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); 23 24 //CompilerParameters 编译参数 25 CompilerParameters objCompilerParameters = new CompilerParameters(); 26 objCompilerParameters.ReferencedAssemblies.Add("System.dll"); 27 objCompilerParameters.ReferencedAssemblies.Add("System.Core.dll"); 28 objCompilerParameters.ReferencedAssemblies.Add("System.Data.dll"); 29 objCompilerParameters.ReferencedAssemblies.Add("CodeMaker.BLL.dll"); 30 objCompilerParameters.ReferencedAssemblies.Add("CodeMaker.DALFactory.dll"); 31 objCompilerParameters.ReferencedAssemblies.Add("CodeMaker.IDAL.dll"); 32 objCompilerParameters.ReferencedAssemblies.Add("CodeMaker.Model.dll"); 33 objCompilerParameters.ReferencedAssemblies.Add("CodeMaker.MySqlDAL.dll"); 34 objCompilerParameters.ReferencedAssemblies.Add("CodeMaker.SqlDAL.dll"); 35 objCompilerParameters.ReferencedAssemblies.Add("CodeMaker.Engine.dll"); 36 objCompilerParameters.GenerateExecutable = false; 37 objCompilerParameters.GenerateInMemory = true; 38 39 // CompilerResults 40 CompilerResults cr = provider.CompileAssemblyFromSource(objCompilerParameters, strCode); 41 42 if (cr.Errors.HasErrors) 43 { 44 Console.WriteLine("编译错误:"); 45 foreach (CompilerError err in cr.Errors) 46 { 47 strResults.Append(err.ErrorText); 48 strResults.Append(Environment.NewLine); 49 strResults.Append(err.Line); 50 strResults.Append(Environment.NewLine); 51 strResults.Append(err.ToString()); 52 strResults.Append(Environment.NewLine); 53 54 } 55 } 56 else 57 { 58 // 通过反射,调用OutPut的输出方法 59 Assembly objAssembly = cr.CompiledAssembly; 60 object objHelloWorld = objAssembly.CreateInstance("DynamicCodeGenerate.CodeGenerate"); 61 MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut"); 62 63 strResults.Append(objMI.Invoke(objHelloWorld, null)); 64 strResults.Append(Environment.NewLine); 65 66 } 67 68 69 return strResults.ToString(); 70 } 71 72 public static string DoCodeMakerCompile(string strDBType,string DALAssemblyPath, string strDataBase,string strTableName, string strEntityName,string strCode) 73 { 74 75 76 StringBuilder sb = new StringBuilder(); 77 //加上要编译部分代码的头部和尾部 78 //头部 79 sb.Append("using System;"); 80 sb.Append("using System.Data;"); 81 sb.Append("using System.Text;"); 82 sb.Append("using System.Linq;"); 83 sb.Append("using System.Globalization;"); 84 sb.Append("using System.Collections.Generic;"); 85 sb.Append("using CodeMaker.Model;"); 86 sb.Append("using CodeMaker.BLL;"); 87 sb.Append("using CodeMaker.Engine;"); 88 sb.Append("namespace DynamicCodeGenerate"); 89 sb.Append("{"); 90 91 92 93 sb.Append(" public class CodeGenerate"); 94 sb.Append(" {"); 95 sb.Append(" public string OutPut()"); 96 sb.Append(" {"); 97 98 //读取数据实体的属性的代码段 99 sb.Append(GetEntity(strDBType, DALAssemblyPath, strDataBase, strTableName, strEntityName)); 100 101 sb.Append(strCode); 102 103 //返回值,字符串 104 sb.Append(" return s.ToString(); "); 105 sb.Append(" }"); 106 //fOutPut方法结束 107 //首字母大写方法 108 sb.Append(" public string ToTitleCase(string str)"); 109 sb.Append(" {"); 110 sb.Append(" return str.Substring(0,1).ToUpper()+str.Substring(1);"); 111 sb.Append(" }"); 112 //首字母小写方法 113 sb.Append(" public string ToLowerCase(string str)"); 114 sb.Append(" {"); 115 sb.Append(" return str.Substring(0,1).ToLower()+str.Substring(1);"); 116 sb.Append(" }"); 117 118 sb.Append(" }"); 119 sb.Append("}"); 120 121 return DoCompile(sb.ToString()); 122 } 123 124 private static string GetEntity(string strDBType, string DALAssemblyPath, string strDataBase, string strTableName, string strEntityName) 125 { 126 StringBuilder sb = new StringBuilder(); 127 sb.Append("CodeMaker.BLL.EntityBLL bll = new CodeMaker.BLL.EntityBLL(\"" + DALAssemblyPath + "\");"); 128 sb.Append("IList<CodeMaker.Model.Entity> es = bll.GetEntityList(\"" + strDataBase + "\", \"" + strTableName + "\");"); 129 sb.Append("string EntityName=\"" + strEntityName + "\";");//实体名,供模板中的代码段使用 130 sb.Append("string TableName=\"" + strTableName + "\";");//表名,供模板中的代码段使用 131 sb.Append("string DBType=\"" + strDBType + "\";");//数据库组件,判断数据库种类SQLSERVER,MYSQL,供模板中的代码段使用 132 sb.Append("string TablePri=(es.Where(x=>x.IsPri==\"YES\").Count()>0)?es.Where(x=>x.IsPri==\"YES\").ToList()[0].ColumnName:\"\";");//表的主键列 名称 133 sb.Append("string TablePriDataType=(es.Where(x=>x.IsPri==\"YES\").Count()>0)?CodeAnalysis.ToDataTypeFormat(es.Where(x=>x.IsPri==\"YES\").ToList()[0].DataType,DBType):\"\";");//表的主键列 数据类型 134 return sb.ToString(); 135 136 } 137 138 public static string GenerateCode() 139 { 140 return ""; 141 } 142 } 143 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Text.RegularExpressions; 6 7 namespace CodeMaker.Engine 8 { 9 public class CodeAnalysis 10 { 11 public static string Hello() 12 { 13 return "Hello"; 14 } 15 16 public static string ToCSharpCode(string strContent) 17 { 18 StringBuilder sb = new StringBuilder(); 19 //需要逐行解析 20 string[] ss = strContent.Split('\n'); 21 string strT=string.Empty; 22 if (ss.Length > 0) 23 { 24 sb.Append("StringBuilder s = new StringBuilder();");//如果行数不为0,则需要声明字符串拼接 25 sb.Append(System.Environment.NewLine); 26 } 27 for (int i = 0; i < ss.Length; i++) 28 { 29 //处理字符串行 30 sb.Append(DealCode(ss[i])); 31 sb.Append(System.Environment.NewLine); 32 33 34 } 35 36 return sb.ToString(); 37 } 38 39 /// <summary> 40 /// 单行字符串处理 41 /// </summary> 42 /// <param name="strLine"></param> 43 /// <returns></returns> 44 private static string DealCode(string strLine) 45 { 46 //判断当该行是无特殊代码行。特殊代码(<-$、$->) 47 48 strLine = Regex.Replace(strLine, @"[\r\n]", ""); //替换掉常量中的换行符 49 50 51 if (strLine.Contains("<-$") && strLine.Contains("$->")) 52 { 53 //有整行特殊代码段 54 //strLine = strLine.Replace("\"", "\\\""); 55 strLine = strLine.Replace("<-$", ""); 56 strLine = strLine.Replace("$->", ""); 57 58 //strLine += "s.Append(System.Environment.NewLine);"; 59 } 60 else if (strLine.Contains("<+$") && strLine.Contains("$+>")) 61 { 62 //有变量取值代码段 63 strLine = strLine.Replace("\"", "\\\""); 64 strLine = "\""+strLine+"\\n\"";//前后先加引号,后面加个换行 65 strLine = strLine.Replace("<+$", "\"+"); 66 strLine = strLine.Replace("$+>", "+\""); 67 68 69 strLine = "s.Append("+ strLine +");"; 70 } 71 else 72 { 73 //不是特殊代码行 74 //strLine = "s.Append(\"" + strLine + "\"); s.Append(System.Environment.NewLine);" ; 75 strLine = strLine.Replace("\"", "\\\""); 76 strLine = "s.Append(\"" + strLine + "\\n\");"; 77 } 78 79 return strLine; 80 } 81 82 #region 供动态编译的代码段中调用的静态方法 83 84 /// <summary> 85 /// 数据库字段数据类型 转为 java语言中的数据类型 86 /// </summary> 87 /// <param name="strDBColumnType">数据库字段数据类型</param> 88 /// <param name="strDBType">数据库MYSQL SQLSERVER</param> 89 /// <returns></returns> 90 public static string ToJavaDataType(string strDBColumnType, string strDBType) 91 { 92 string strT = string.Empty; 93 94 //根据strDBType 判断数据库是什么,然后转换为程序语言中的数据类型 95 switch (strDBType) 96 { 97 case "SQLSERVER": 98 var stringwords = new string[]{"char","varchar","text","nchar","nvarchar","ntext"}; 99 var intwords = new string[]{"int","smallint","tinyint"}; 100 var boolwords = new string[] { "bit"}; 101 var longwords = new string[] { "bigint"}; 102 var decimalwords = new string[] { "numeric", "decimal", "money","smallmoney","float","real" }; 103 var datewords = new string[] { "datetime", "smalldatetime" }; 104 if (stringwords.Contains(strDBColumnType.ToLower())) 105 { 106 strT="String"; 107 } 108 else if (intwords.Contains(strDBColumnType.ToLower())) 109 { 110 strT = "int"; 111 } 112 else if (longwords.Contains(strDBColumnType.ToLower())) 113 { 114 strT = "long"; 115 } 116 else if (boolwords.Contains(strDBColumnType.ToLower())) 117 { 118 strT = "boolean"; 119 } 120 else if (decimalwords.Contains(strDBColumnType.ToLower())) 121 { 122 strT = "decimal"; 123 } 124 else if (datewords.Contains(strDBColumnType.ToLower())) 125 { 126 strT = "DateTime"; 127 } 128 else 129 { 130 strT = "String"; 131 } 132 133 134 break; 135 136 case "MYSQL": 137 var stringwords1 = new string[]{"char","varchar","text","tinytext","mediumtext","longtext"}; 138 var intwords1 = new string[]{"smallint","tinyint","mediumint"}; 139 var boolwords1 = new string[] { "bit"}; 140 var longwords1 = new string[] { "int,bigint", "integer" }; 141 var decimalwords1 = new string[] { "float", "decimal", "double" }; 142 var datewords1 = new string[] { "datetime", "date" }; 143 if (stringwords1.Contains(strDBColumnType.ToLower())) 144 { 145 strT = "String"; 146 } 147 else if (intwords1.Contains(strDBColumnType.ToLower())) 148 { 149 strT = "int"; 150 } 151 else if (longwords1.Contains(strDBColumnType.ToLower())) 152 { 153 strT = "long"; 154 } 155 else if (boolwords1.Contains(strDBColumnType.ToLower())) 156 { 157 strT = "boolean"; 158 } 159 else if (decimalwords1.Contains(strDBColumnType.ToLower())) 160 { 161 strT = "decimal"; 162 } 163 else if (datewords1.Contains(strDBColumnType.ToLower())) 164 { 165 strT = "DateTime"; 166 } 167 else 168 { 169 strT = "String"; 170 } 171 172 173 break; 174 175 default: 176 break; 177 } 178 179 return strT; 180 } 181 182 /// <summary> 183 /// 数据库字段数据类型 转为 c# 语言中的数据类型 184 /// </summary> 185 /// <param name="strDBColumnType">数据库字段数据类型</param> 186 /// <param name="strDBType">数据库MYSQL SQLSERVER</param> 187 /// <returns></returns> 188 public static string ToCSDataType(string strDBColumnType, string strDBType) 189 { 190 string strT = string.Empty; 191 192 //根据strDBType 判断数据库是什么,然后转换为程序语言中的数据类型 193 switch (strDBType) 194 { 195 case "SQLSERVER": 196 var stringwords = new string[]{"char","varchar","text","nchar","nvarchar","ntext"}; 197 var intwords = new string[]{"int","smallint","tinyint"}; 198 var boolwords = new string[] { "bit"}; 199 var longwords = new string[] { "bigint"}; 200 var decimalwords = new string[] { "numeric", "decimal", "money","smallmoney","float","real" }; 201 var datewords = new string[] { "datetime", "smalldatetime" }; 202 if (stringwords.Contains(strDBColumnType.ToLower())) 203 { 204 strT="string"; 205 } 206 else if (intwords.Contains(strDBColumnType.ToLower())) 207 { 208 strT = "int"; 209 } 210 else if (longwords.Contains(strDBColumnType.ToLower())) 211 { 212 strT = "long"; 213 } 214 else if (boolwords.Contains(strDBColumnType.ToLower())) 215 { 216 strT = "bool"; 217 } 218 else if (decimalwords.Contains(strDBColumnType.ToLower())) 219 { 220 strT = "decimal"; 221 } 222 else if (datewords.Contains(strDBColumnType.ToLower())) 223 { 224 strT = "DateTime"; 225 } 226 else 227 { 228 strT = "string"; 229 } 230 231 232 break; 233 234 case "MYSQL": 235 var stringwords1 = new string[]{"char","varchar","text","tinytext","mediumtext","longtext"}; 236 var intwords1 = new string[]{"smallint","tinyint","mediumint"}; 237 var boolwords1 = new string[] { "bit"}; 238 var longwords1 = new string[] { "int,bigint", "integer" }; 239 var decimalwords1 = new string[] { "float", "decimal", "double" }; 240 var datewords1 = new string[] { "datetime", "date" }; 241 if (stringwords1.Contains(strDBColumnType.ToLower())) 242 { 243 strT="string"; 244 } 245 else if (intwords1.Contains(strDBColumnType.ToLower())) 246 { 247 strT = "int"; 248 } 249 else if (longwords1.Contains(strDBColumnType.ToLower())) 250 { 251 strT = "long"; 252 } 253 else if (boolwords1.Contains(strDBColumnType.ToLower())) 254 { 255 strT = "bool"; 256 } 257 else if (decimalwords1.Contains(strDBColumnType.ToLower())) 258 { 259 strT = "decimal"; 260 } 261 else if (datewords1.Contains(strDBColumnType.ToLower())) 262 { 263 strT = "DateTime"; 264 } 265 else 266 { 267 strT = "string"; 268 } 269 270 271 break; 272 273 default: 274 break; 275 } 276 277 return strT; 278 } 279 280 /// <summary> 281 /// 把小写的sqlserver数据库中的数据类型转为sqlserver参数格式,例如 SqlDbType.VarChar 282 /// </summary> 283 /// <param name="strDataType"></param> 284 /// <param name="strDBType">数据库MYSQL SQLSERVER</param> 285 /// <returns></returns> 286 public static string ToDataTypeFormat(string strDataType,string strDBType) 287 { 288 string strT = string.Empty; 289 switch (strDataType.ToLower()) 290 { 291 case "int": 292 strT = "Int"; 293 break; 294 case "varchar": 295 strT = "VarChar"; 296 break; 297 case "char": 298 strT = "Char"; 299 break; 300 case "bigint": 301 strT = "BigInt"; 302 break; 303 case "nvarchar": 304 strT = "NVarChar"; 305 break; 306 case "datetime": 307 strT = "DateTime"; 308 break; 309 case "smalldatetime": 310 strT = "SmallDateTime"; 311 break; 312 case "bit": 313 strT = "Bit"; 314 break; 315 case "text": 316 strT = "Text"; 317 318 break; 319 case "decimal": 320 strT = "Decimal"; 321 break; 322 case "ntext": 323 strT = "NText"; 324 break; 325 default: 326 strT = "VarChar"; 327 break; 328 } 329 330 return strT; 331 } 332 333 /// <summary> 334 /// 获取数据类型或控件的简写,用于前缀命名 335 /// </summary> 336 /// <param name="strLongName"></param> 337 /// <returns></returns> 338 public static string ToNameFormat(string strLongName) 339 { 340 string strT = string.Empty; 341 switch (strLongName.ToLower()) 342 { 343 case "int": 344 strT = "int"; 345 break; 346 case "string": 347 strT = "str"; 348 break; 349 case "char": 350 strT = "ch"; 351 break; 352 case "long": 353 strT = "long"; 354 break; 355 case "float": 356 strT = "float"; 357 break; 358 case "datetime": 359 strT = "date"; 360 break; 361 case "double": 362 strT = "double"; 363 break; 364 case "bool": 365 strT = "Is"; 366 break; 367 case "decimal": 368 strT = "dec"; 369 break; 370 case "boolean": 371 strT = "Is"; 372 break; 373 default: 374 strT = "x"; 375 break; 376 } 377 378 return strT; 379 } 380 #endregion 381 } 382 }
--------------------------------------------------------------------------
有位博友提到过T4模板,我也看了一点点,但是我考虑的是不单单生成c#代码,目标代码还要java,因为目前正在转java方向。为了灵活性,我觉得自己定义规则比较放心,也许这个想法不成熟,但是先试试吧
下载链接
http://www.cnblogs.com/allanyang/p/4702467.html