首页 > 学院 > 开发设计 > 正文

x01.CodeBuilder:生成代码框架

2019-11-14 13:41:32
字体:
来源:转载
供稿:网友

根据 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


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表