年前用过李天平前辈的,自己改过,后来李老师做动软了,不给源码,修改不是很方便。加上我目前需要转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('
');
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, @"[
]", ""); //替换掉常量中的换行符
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