你的位置:首页 > ASP.net教程

[ASP.net教程]x01.CodeBuilder: 生成代码框架


根据 Assembly 生成代码框架。

这是学习 AvalonEdit 的一个副产品。学习时,照着源代码新建文件夹,新建文件,添加方法与属性,虽然只是个框架,也要花费大量时间。为什么不让它自动生成呢?于是,新建了个控制台程序,一步步添加,一步步显示,一步步调整。虽然还有许多不完善的地方,但它基本能用了。将 Main 方法略作改动,便成了 Build 方法。为操作方便,加了个 WPF 界面。OK!下一步可参照 ILSpy 来进行改写,当也是一款不错的工具吧。限于时间与能力,暂且作罢。

主要代码如下:

 1 /** 2  * Program.cs (c) 2015 by x01 3 */ 4 using System; 5 using System.Collections.Generic; 6 using System.Diagnostics; 7 using System.IO; 8 using System.Linq; 9 using System.Reflection; 10 using System.Text; 11 using System.Text.RegularExpressions; 12 using System.Windows; 13  14 namespace x01.CodeBuilder 15 { 16   public class Test<THllo> 17   { 18      19   } 20   /// <summary> 21   /// Description of Program. 22   /// </summary> 23   public static class BuildHelper 24   { 25     static readonly StringBuilder sb = new StringBuilder(); 26     static readonly List<string> usings = new List<string>(); 27     static string headerFormat = "/**\n * {0}.cs (c) 2015 by x01\n */\n"; 28      29     /// <summary> 30     /// 根据 Assebmly 生成代码框架。 31     /// </summary> 32     /// <param name="path">程序集路径名</param> 33     /// <param name="outputDirectory">输出目录</param> 34     public static void Build(string path, string outputDirectory) 35     { 36       if (!File.Exists(path)) { 37         throw new Exception("Assembly file not found."); 38       } 39       if (!Directory.Exists(outputDirectory)) { 40         Directory.CreateDirectory(outputDirectory); 41       } 42        43       Assembly assembly = Assembly.LoadFile(path); 44       string assemblyName = assembly.FullName.Split(',')[0]; 45        46       string assemblyPath = Path.GetDirectoryName(assembly.Location); 47       foreach (var type in assembly.GetTypes()) { 48         usings.Clear(); 49          50         if (!(type.IsEnum || type.IsClass || type.IsInterface || type.IsGenericType)) { 51           continue; 52         } 53          54         string typeName = type.FullName.Replace(assemblyName + ".",""); 55          56         string[] typeNameSplits = typeName.Split('.'); 57         string fileDirectory = outputDirectory; 58         if (typeNameSplits.Length > 1) { 59           for (int i = 0; i < typeNameSplits.Length - 1; i++) { 60             fileDirectory += "\\" + typeNameSplits[i]; 61             if (!Directory.Exists(fileDirectory)) { 62               Directory.CreateDirectory(fileDirectory); 63             } 64           } 65         } 66          67         sb.Clear(); 68         int lastDotIndex = type.FullName.LastIndexOf('.'); 69         string namespaceName = lastDotIndex > 0 ? type.FullName.Substring(0,lastDotIndex) : type.FullName; 70          71         sb.Append("namespace " + namespaceName + "\n{\n"); 72          73         string convertName = ConvertType(type.Name);  74         sb.Append("\t//TODO: " + convertName + "\n"); 75        76         if (type.IsPublic) { 77           sb.Append("\tpublic "); 78         } else { 79           sb.Append("\t"); 80         } 81          82         if (type.IsAbstract && !type.IsInterface) { 83           sb.Append("abstract "); 84         } else if (type.IsSealed && !type.IsEnum) { 85           sb.Append("sealed "); 86         } 87          88         if (type.IsEnum) { 89           sb.Append("enum "); 90         } else if (type.IsClass) { 91           sb.Append("class "); 92         } else if (type.IsInterface) { 93           sb.Append("interface "); 94         } 95          96         sb.Append(convertName);  97         if (type.BaseType != null && !string.IsNullOrEmpty(type.BaseType.Name)) { 98           sb.Append(" : " + ConvertType(type.BaseType.Name)); 99         }100         sb.Append("\n\t{\n");101         102         var baseProperties = type.BaseType != null ? type.BaseType.GetProperties() : new PropertyInfo[1];103         foreach (var property in type.GetProperties()) {104           if (type.IsEnum) continue;105           106           var propertyString = property.ToString();107           bool skip = false;108           foreach (var bp in baseProperties) {109             if (bp == null) continue;110             if (propertyString == bp.ToString()) {111               skip = true;112               break;113             }114           }115           if (skip) continue;116           117           int lastIndex = propertyString.LastIndexOf('.');118           string propu = string.Empty;119           if (lastIndex >= 0)120             propu = propertyString.Substring(0,lastIndex);121           propu = ConvertType(propu);122           if (!usings.Contains(propu) && !string.IsNullOrEmpty(propu)) {123             usings.Add(propu);124           }125           string p = propertyString.Substring(lastIndex+1);126           string[] ps = p.Split(' ');127           ps[0] = ConvertType(ps[0]) + " ";128           p = string.Empty;129           for (int i = 0; i < ps.Length; i++) {130             p += ps[i];131           }132           sb.Append("\t\tpublic " + p + " { get; set; }\n");133         }134   135         sb.Append("\n");136         137         var baseMethods = type.BaseType != null ? type.BaseType.GetMethods() : new MethodInfo[1];138         foreach (var method in type.GetMethods()) {139           if (type.IsEnum) continue;140           141           bool skip = false;142           foreach (var bm in baseMethods) {143             if (bm == null) break;144             if (bm.ToString() == method.ToString()) {145               skip = true;146               break;147             }148           }149           if (skip) continue;150           151           var typeString = method.ReturnType.ToString();152           if (method.Name.Contains("get_") || method.Name.Contains("set_") 153             || method.Name.Contains("add_") || method.Name.Contains("remove_")) {154             continue;155           }156           int lastIndex = typeString.LastIndexOf('.');157           string r = string.Empty;158           if (lastIndex > 0) {159             string u = typeString.Substring(0,lastIndex);160             u = ConvertType(u);161             if (!usings.Contains(u) && !string.IsNullOrEmpty(u)) {162               usings.Add(u);163             }164             r = typeString.Substring(lastIndex+1);165           } else {166             r = typeString;167           }168           r = ConvertType(r);169           sb.Append("\t\tpublic " + r + " " + method.Name + "(");170           int pcount = method.GetParameters().Length;171           int count = 0;172           foreach (var parameter in method.GetParameters()) {173             var paramString = parameter.ParameterType.ToString();174             int plast = paramString.LastIndexOf('.');175             string ptype = string.Empty;176             if (plast > 0) {177               string pu = paramString.Substring(0, plast);178               pu = ConvertType(pu);179               if (!usings.Contains(pu)) {180                 usings.Add(pu);181               }182               ptype = paramString.Substring(plast+1);183             } else {184               ptype = paramString;185             }186             ptype = ConvertType(ptype);187             count ++;188             if (pcount == 1 || pcount == count)189               sb.Append(ptype + " " + parameter.Name);190             else 191               sb.Append(ptype + " " + parameter.Name + ", ");192           }193           sb.Append(")\n");194           sb.Append("\t\t{\n\t\t\tthrow new NotImplementedException();\n\t\t}\n");195         }196         197         sb.Append("\t}\n"); // end type198         199         sb.Append("}"); //end namespace200         201         string header = string.Format(headerFormat, convertName);202         string ustring = header;203         foreach (var us in usings) {204           ustring += "using " + us + ";\n";205         }206         ustring += "\n" + sb.ToString();207 208         if (!string.IsNullOrEmpty(convertName)) {209           string filename = Path.Combine(fileDirectory, convertName) + ".cs";210           File.WriteAllText(filename, ustring);211         }212       }213     }214     215     static string ConvertType(string typeName)216     {217       int index = typeName.IndexOf('`');218       if (index >= 0)219         typeName = typeName.Substring(0,index);220       index = typeName.IndexOf('+');221       if (index >= 0) 222         typeName = typeName.Substring(0,index);223       index = typeName.IndexOf('<');224       if (index >= 0)225         typeName = typeName.Substring(0,index);226       index = typeName.IndexOf(']');227       if (index >= 0)228         typeName = typeName.Substring(0, index);229       230       switch (typeName) {231         case "Boolean":232           return "bool";233         case "Void":234           return "void";235         case "Int32":236           return "int";237         case "Object":238           return "object";239         case "Double":240           return "double";241         case "String":242           return "string";243         case "Long":244           return "long";245         default:246           break;247       }248       249       return typeName;250     }251     252     // 测试用的。253 //    static void Main(string[] args)254 //    {255 //      string path = @"E:\Temp\Lab\x01\x01.CodeBuilder\bin\Debug\x01.MelonEdit.exe";256 //      string target = @"E:\Temp\Lab\x01\Output";257 //      Build(path,target);258 //      259 //      Console.ReadKey(true);260 //    }261   }262 }

View Code

看一看,真是惨不忍睹。这大概就是所谓的意大利面条吧。

源代码下载:https://github.com/chinax01/x01.CodeBuilder