x01.CodeBuilder: 生成代码框架
2015-12-07 16:21
417 查看
根据 Assembly 生成代码框架。
这是学习 AvalonEdit 的一个副产品。学习时,照着源代码新建文件夹,新建文件,添加方法与属性,虽然只是个框架,也要花费大量时间。为什么不让它自动生成呢?于是,新建了个控制台程序,一步步添加,一步步显示,一步步调整。虽然还有许多不完善的地方,但它基本能用了。将 Main 方法略作改动,便成了 Build 方法。为操作方便,加了个 WPF 界面。OK!下一步可参照 ILSpy 来进行改写,当也是一款不错的工具吧。限于时间与能力,暂且作罢。
主要代码如下:
View Code
看一看,真是惨不忍睹。这大概就是所谓的意大利面条吧。
源代码下载:https://github.com/chinax01/x01.CodeBuilder
这是学习 AvalonEdit 的一个副产品。学习时,照着源代码新建文件夹,新建文件,添加方法与属性,虽然只是个框架,也要花费大量时间。为什么不让它自动生成呢?于是,新建了个控制台程序,一步步添加,一步步显示,一步步调整。虽然还有许多不完善的地方,但它基本能用了。将 Main 方法略作改动,便成了 Build 方法。为操作方便,加了个 WPF 界面。OK!下一步可参照 ILSpy 来进行改写,当也是一款不错的工具吧。限于时间与能力,暂且作罢。
主要代码如下:
/** * Program.cs (c) 2015 by x01 */ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; using System.Windows; namespace x01.CodeBuilder { public class Test<THllo> { } /// <summary> /// Description of Program. /// </summary> public static class BuildHelper { static readonly StringBuilder sb = new StringBuilder(); static readonly List<string> usings = new List<string>(); static string headerFormat = "/**\n * {0}.cs (c) 2015 by x01\n */\n"; /// <summary> /// 根据 Assebmly 生成代码框架。 /// </summary> /// <param name="path">程序集路径名</param> /// <param name="outputDirectory">输出目录</param> public static void Build(string path, string outputDirectory) { if (!File.Exists(path)) { throw new Exception("Assembly file not found."); } if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } Assembly assembly = Assembly.LoadFile(path); string assemblyName = assembly.FullName.Split(',')[0]; string assemblyPath = Path.GetDirectoryName(assembly.Location); foreach (var type in assembly.GetTypes()) { usings.Clear(); if (!(type.IsEnum || type.IsClass || type.IsInterface || type.IsGenericType)) { continue; } string typeName = type.FullName.Replace(assemblyName + ".",""); string[] typeNameSplits = typeName.Split('.'); string fileDirectory = outputDirectory; if (typeNameSplits.Length > 1) { for (int i = 0; i < typeNameSplits.Length - 1; i++) { fileDirectory += "\\" + typeNameSplits[i]; if (!Directory.Exists(fileDirectory)) { Directory.CreateDirectory(fileDirectory); } } } sb.Clear(); int lastDotIndex = type.FullName.LastIndexOf('.'); string namespaceName = lastDotIndex > 0 ? type.FullName.Substring(0,lastDotIndex) : type.FullName; sb.Append("namespace " + namespaceName + "\n{\n"); string convertName = ConvertType(type.Name); sb.Append("\t//TODO: " + convertName + "\n"); if (type.IsPublic) { sb.Append("\tpublic "); } else { sb.Append("\t"); } if (type.IsAbstract && !type.IsInterface) { sb.Append("abstract "); } else if (type.IsSealed && !type.IsEnum) { sb.Append("sealed "); } if (type.IsEnum) { sb.Append("enum "); } else if (type.IsClass) { sb.Append("class "); } else if (type.IsInterface) { sb.Append("interface "); } sb.Append(convertName); if (type.BaseType != null && !string.IsNullOrEmpty(type.BaseType.Name)) { sb.Append(" : " + ConvertType(type.BaseType.Name)); } sb.Append("\n\t{\n"); var baseProperties = type.BaseType != null ? type.BaseType.GetProperties() : new PropertyInfo[1]; foreach (var property in type.GetProperties()) { if (type.IsEnum) continue; var propertyString = property.ToString(); bool skip = false; foreach (var bp in baseProperties) { if (bp == null) continue; if (propertyString == bp.ToString()) { skip = true; break; } } if (skip) continue; int lastIndex = propertyString.LastIndexOf('.'); string propu = string.Empty; if (lastIndex >= 0) propu = propertyString.Substring(0,lastIndex); propu = ConvertType(propu); if (!usings.Contains(propu) && !string.IsNullOrEmpty(propu)) { usings.Add(propu); } string p = propertyString.Substring(lastIndex+1); string[] ps = p.Split(' '); ps[0] = ConvertType(ps[0]) + " "; p = string.Empty; for (int i = 0; i < ps.Length; i++) { p += ps[i]; } sb.Append("\t\tpublic " + p + " { get; set; }\n"); } sb.Append("\n"); var baseMethods = type.BaseType != null ? type.BaseType.GetMethods() : new MethodInfo[1]; foreach (var method in type.GetMethods()) { if (type.IsEnum) continue; bool skip = false; foreach (var bm in baseMethods) { if (bm == null) break; if (bm.ToString() == method.ToString()) { skip = true; break; } } if (skip) continue; var typeString = method.ReturnType.ToString(); if (method.Name.Contains("get_") || method.Name.Contains("set_") || method.Name.Contains("add_") || method.Name.Contains("remove_")) { continue; } int lastIndex = typeString.LastIndexOf('.'); string r = string.Empty; if (lastIndex > 0) { string u = typeString.Substring(0,lastIndex); u = ConvertType(u); if (!usings.Contains(u) && !string.IsNullOrEmpty(u)) { usings.Add(u); } r = typeString.Substring(lastIndex+1); } else { r = typeString; } r = ConvertType(r); sb.Append("\t\tpublic " + r + " " + method.Name + "("); int pcount = method.GetParameters().Length; int count = 0; foreach (var parameter in method.GetParameters()) { var paramString = parameter.ParameterType.ToString(); int plast = paramString.LastIndexOf('.'); string ptype = string.Empty; if (plast > 0) { string pu = paramString.Substring(0, plast); pu = ConvertType(pu); if (!usings.Contains(pu)) { usings.Add(pu); } ptype = paramString.Substring(plast+1); } else { ptype = paramString; } ptype = ConvertType(ptype); count ++; if (pcount == 1 || pcount == count) sb.Append(ptype + " " + parameter.Name); else sb.Append(ptype + " " + parameter.Name + ", "); } sb.Append(")\n"); sb.Append("\t\t{\n\t\t\tthrow new NotImplementedException();\n\t\t}\n"); } sb.Append("\t}\n"); // end type sb.Append("}"); //end namespace string header = string.Format(headerFormat, convertName); string ustring = header; foreach (var us in usings) { ustring += "using " + us + ";\n"; } ustring += "\n" + sb.ToString(); if (!string.IsNullOrEmpty(convertName)) { string filename = Path.Combine(fileDirectory, convertName) + ".cs"; File.WriteAllText(filename, ustring); } } } static string ConvertType(string typeName) { int index = typeName.IndexOf('`'); if (index >= 0) typeName = typeName.Substring(0,index); index = typeName.IndexOf('+'); if (index >= 0) typeName = typeName.Substring(0,index); index = typeName.IndexOf('<'); if (index >= 0) typeName = typeName.Substring(0,index); index = typeName.IndexOf(']'); if (index >= 0) typeName = typeName.Substring(0, index); switch (typeName) { case "Boolean": return "bool"; case "Void": return "void"; case "Int32": return "int"; case "Object": return "object"; case "Double": return "double"; case "String": return "string"; case "Long": return "long"; default: break; } return typeName; } // 测试用的。 // static void Main(string[] args) // { // string path = @"E:\Temp\Lab\x01\x01.CodeBuilder\bin\Debug\x01.MelonEdit.exe"; // string target = @"E:\Temp\Lab\x01\Output"; // Build(path,target); // // Console.ReadKey(true); // } } }
View Code
看一看,真是惨不忍睹。这大概就是所谓的意大利面条吧。
源代码下载:https://github.com/chinax01/x01.CodeBuilder
相关文章推荐
- Uincode和ASCLL
- BlockingQueue的使用
- java.lang.SecurityException: Need BLUETOOTH_PRIVILEGED permission:
- 根据内容自动调节cell的高度
- 创建圆角 抛出一个错误:二元运算符“|”不能用于两个UIRectCorner操作数
- Build.prop重要参数解释
- Java中parse()和valueOf(),toString()的区别
- 优化UITableView滚动的流畅性
- 解析request的反馈信息
- UITextField的提示文字水平居中
- UIScrollView循环滚动(前后各加一张图片)
- The request sent by the client was syntactically incorrect ()问题
- UID_PS_01_大师之路
- APUE学习之----进程通信pipe实现管道
- 队列ArrayBlockingQueue的使用
- 偶然翻出很久很久以前写的一款sqlmap UI,有点年头了
- 基于jQuey实现鼠标滑过变色(整行变色)
- django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE的解决办法
- UI控件-UITextField
- [DP] Unique Binary Search Trees