Generator.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. using System.Collections.Generic;
  2. using System.Text.RegularExpressions;
  3. using System.Threading.Tasks;
  4. using EnvDTE;
  5. using Microsoft.VisualStudio.Shell;
  6. using VberAdmin.Models;
  7. namespace VberAdmin.Generating
  8. {
  9. public class Generator
  10. {
  11. private DTE Dte { get; }
  12. public TemplateViewModel ViewModel { get; set; }
  13. private IFileCreate Creator { get; set; }
  14. public Generator(DTE dte, IFileCreate creator)
  15. {
  16. ThreadHelper.ThrowIfNotOnUIThread();
  17. Dte = dte;
  18. ViewModel = GetViewModel();
  19. Creator = creator;
  20. }
  21. /// <summary>
  22. /// 执行生成文件
  23. /// </summary>
  24. public async Task ExecuteAsync()
  25. {
  26. await Creator.CreateAsync(ViewModel);
  27. }
  28. #region 获取模板模型
  29. /// <summary>
  30. /// 获取模板模型
  31. /// </summary>
  32. /// <returns></returns>
  33. private TemplateViewModel GetViewModel()
  34. {
  35. ThreadHelper.ThrowIfNotOnUIThread();
  36. Document doc = Dte.ActiveDocument;
  37. var projectItem = doc.ProjectItem;
  38. var project = projectItem.ContainingProject;
  39. TemplateViewModel model = new TemplateViewModel
  40. {
  41. ProjectName = project.Name.Replace(".Core", ""),
  42. BaseFolder = doc.Path
  43. };
  44. TextSelection sel = (TextSelection)doc.Selection;
  45. // ReSharper disable once SuspiciousTypeConversion.Global
  46. if (sel.ActivePoint.CodeElement[vsCMElement.vsCMElementClass] is CodeClass codeClass)
  47. {
  48. model.ClassNamespace = codeClass.Namespace.Name;
  49. model.HtmlPageTitle = ConvertDocComment(codeClass.DocComment);
  50. model.HtmlModalTitle = model.HtmlPageTitle;
  51. model.ClassName = codeClass.Name;
  52. foreach (CodeElement element in codeClass.Bases)
  53. {
  54. string name = element.FullName ?? "";
  55. string typeStr = Regex.Match(name, "(?<=<).*?(?=>)").Value;
  56. if (typeStr.Contains("System.Int32"))
  57. {
  58. model.IdType = "int";
  59. }
  60. else if (typeStr.Contains("System.Int64"))
  61. {
  62. model.IdType = "long";
  63. }
  64. else if (typeStr.Contains("System.String"))
  65. {
  66. model.IdType = "string";
  67. }
  68. else if (typeStr.Contains("System.Guid"))
  69. {
  70. model.IdType = "Guid";
  71. }
  72. if (!string.IsNullOrEmpty(model.IdType))
  73. break;
  74. }
  75. model.Columns = new List<ColumnViewModel>();
  76. foreach (CodeElement elem in codeClass.Members)
  77. {
  78. if (elem.Kind == vsCMElement.vsCMElementProperty)
  79. {
  80. // ReSharper disable once SuspiciousTypeConversion.Global
  81. if (elem is CodeProperty cp)
  82. {
  83. var attrType = cp.Type.AsString?.ToLower() ?? "";
  84. if (attrType.Contains("string") || attrType.Contains("int") || attrType.Contains("datetime") || attrType.Contains("long") || attrType.Contains("bool") || attrType.Contains("decimal") || attrType.Contains("short") || attrType.Contains("double") || attrType.Contains("float") || attrType.Contains("guid"))
  85. {
  86. var column = new ColumnViewModel
  87. {
  88. ColumnName = cp.Name,
  89. Comment = ConvertDocComment(cp.DocComment),
  90. AttrType = cp.Type.AsString?.Replace("System.", ""),
  91. IsGenreated = cp.Name != "CreatorUser" && cp.Name != "LastModifierUser" &&
  92. cp.Name != "DeleterUser"
  93. };
  94. if (cp.Attributes != null)
  95. {
  96. foreach (CodeElement element in cp.Attributes)
  97. {
  98. // ReSharper disable once SuspiciousTypeConversion.Global
  99. CodeAttribute ca = element as CodeAttribute;
  100. if (ca?.Name == "Required")
  101. {
  102. column.IsRequired = true;
  103. }
  104. if (ca?.Name == "MaxLength" || ca?.Name == "StringLength")
  105. {
  106. column.MaxLengthStr = ca.Value;
  107. }
  108. }
  109. }
  110. model.Columns.Add(column);
  111. }
  112. }
  113. }
  114. //else if (elem.Kind == vsCMElement.vsCMElementVariable)
  115. //{
  116. // CodeVariable cv = elem as CodeVariable;
  117. // if (cv != null && cv.Name == "ParentPath")
  118. // {
  119. // }
  120. //
  121. //}
  122. // Debug.WriteLine($"【CodeElement】 :value[{elem.Kind.ToString()}]");
  123. }
  124. }
  125. return model;
  126. }
  127. /// <summary>
  128. /// 获取注释
  129. /// </summary>
  130. /// <param name="docComment"></param>
  131. /// <returns></returns>
  132. private string ConvertDocComment(string docComment)
  133. {
  134. string newComment = docComment.Replace("<doc>\r\n<summary>\r\n", "").Replace("\r\n</summary>\r\n</doc>", "");
  135. return newComment;
  136. }
  137. //private void CodeClass(CodeClass cls)
  138. //{
  139. // string name = cls.Name;
  140. // string classNamespace = cls.Namespace.Name;
  141. // string comment = cls.Comment;
  142. // string docComment = cls.DocComment;
  143. // string infoLocation = cls.InfoLocation.ToString();
  144. // Debug.WriteLine($"【CodeClass】--[Name:{name}]--[Namespace:{classNamespace}]--[Comment:{comment}]--[DocComment:{docComment}]--[InfoLocation:{infoLocation}]");
  145. //}
  146. #endregion 获取模板模型
  147. #region 创建文件
  148. ///// <summary>
  149. ///// 生成DTO
  150. ///// </summary>
  151. //private void CreateDtos()
  152. //{
  153. // ThreadHelper.ThrowIfNotOnUIThread();
  154. // List<string> dtoFiles = new List<string>();
  155. // if (ViewModel.IsCreateDto)
  156. // {
  157. // if (CreateT4<CreateDto>(ViewModel.CreateDtoName))
  158. // dtoFiles.Add(ViewModel.DtoFolder + ViewModel.CreateDtoName);
  159. // }
  160. // if (ViewModel.IsUpdateDto)
  161. // {
  162. // if (CreateT4<UpdateDto>(ViewModel.UpdateDtoName))
  163. // dtoFiles.Add(ViewModel.DtoFolder + ViewModel.UpdateDtoName);
  164. // }
  165. // if (ViewModel.IsUpdateDto)
  166. // {
  167. // if (CreateT4<ListDto>(ViewModel.ListDtoName))
  168. // dtoFiles.Add(ViewModel.DtoFolder + ViewModel.ListDtoName);
  169. // }
  170. // if (dtoFiles.Any())
  171. // AddFilesToProject(ViewModel.ApplicationName, dtoFiles);
  172. //}
  173. ///// <summary>
  174. ///// 生成Application
  175. ///// </summary>
  176. //private void CreateApplications()
  177. //{
  178. // ThreadHelper.ThrowIfNotOnUIThread();
  179. // List<string> applicationFileList = new List<string>();
  180. // if (ViewModel.IsApplicationService)
  181. // {
  182. // if (CreateT4<Service>(ViewModel.ServiceName, 1))
  183. // applicationFileList.Add(ViewModel.ServiceFolder + ViewModel.ServiceName);
  184. // }
  185. // if (ViewModel.IsIApplicationService)
  186. // {
  187. // if (CreateT4<ServiceInterface>(ViewModel.ServiceInterfaceName, 1))
  188. // applicationFileList.Add(ViewModel.ServiceFolder + ViewModel.ServiceInterfaceName);
  189. // }
  190. // if (applicationFileList.Any())
  191. // AddFilesToProject(ViewModel.ApplicationName, applicationFileList);
  192. //}
  193. ///// <summary>
  194. ///// 生成Web
  195. ///// </summary>
  196. //private void CreateWebs()
  197. //{
  198. // ThreadHelper.ThrowIfNotOnUIThread();
  199. // List<string> webFileList = new List<string>();
  200. // if (ViewModel.IsController)
  201. // {
  202. // if (CreateT4<WebController>(ViewModel.ControllerName, 2))
  203. // webFileList.Add(ViewModel.ControllerFolder + ViewModel.ControllerName);
  204. // }
  205. // if (ViewModel.IsView)
  206. // {
  207. // if (CreateT4<WebView>(ViewModel.ViewsName, 3))
  208. // webFileList.Add(ViewModel.ViewsFolder + ViewModel.ViewsName);
  209. // }
  210. // if (webFileList.Any())
  211. // AddFilesToProject(ViewModel.WebName, webFileList);
  212. //}
  213. ///// <summary>
  214. ///// 运用T4模板生成文件
  215. ///// </summary>
  216. ///// <typeparam name="T"></typeparam>
  217. ///// <param name="fileName"></param>
  218. ///// <param name="fileType"></param>
  219. //private bool CreateT4<T>(string fileName, int fileType = 0)
  220. // where T : IT4CodeBase, new()
  221. //{
  222. // ThreadHelper.ThrowIfNotOnUIThread();
  223. // T t4 = new T { Model = ViewModel };
  224. // string pageContent = t4.TransformText();
  225. // string path = ViewModel.DtoFolder;
  226. // switch (fileType)
  227. // {
  228. // case 0:
  229. // path = ViewModel.DtoFolder;
  230. // break;
  231. // case 1:
  232. // path = ViewModel.ServiceFolder;
  233. // break;
  234. // case 2:
  235. // path = ViewModel.ControllerFolder;
  236. // break;
  237. // case 3:
  238. // path = ViewModel.ViewsFolder;
  239. // break;
  240. // }
  241. // return CreateFile(path, fileName, pageContent);
  242. //}
  243. ///// <summary>
  244. ///// 创建文件
  245. ///// </summary>
  246. ///// <param name="sourcePath"></param>
  247. ///// <param name="fileName"></param>
  248. ///// <param name="content"></param>
  249. //private bool CreateFile(string sourcePath, string fileName, string content)
  250. //{
  251. // ThreadHelper.ThrowIfNotOnUIThread();
  252. // string path = Path.GetTempPath();
  253. // Directory.CreateDirectory(path);
  254. // string file = Path.Combine(path, fileName);
  255. // File.WriteAllText(file, content, Encoding.UTF8);
  256. // try
  257. // {
  258. // if (string.IsNullOrEmpty(sourcePath))
  259. // sourcePath = @"..\..\";
  260. // if (!File.Exists(sourcePath))
  261. // Directory.CreateDirectory(sourcePath);
  262. // string sourceUrl = Path.Combine(sourcePath, fileName);
  263. // if (ViewModel.IsReplace)
  264. // File.Delete(sourceUrl);
  265. // if (!File.Exists(sourceUrl))
  266. // {
  267. // File.Copy(file, sourceUrl);
  268. // Dte.StatusBar.Text = $"VberCode:{fileName}代码已生成。";
  269. // return true;
  270. // }
  271. // }
  272. // finally
  273. // {
  274. // File.Delete(file);
  275. // }
  276. // return false;
  277. //}
  278. ///// <summary>
  279. ///// 添加文件到项目中
  280. ///// </summary>
  281. ///// <param name="projectName"></param>
  282. ///// <param name="files"></param>
  283. //public void AddFilesToProject(string projectName, List<string> files)
  284. //{
  285. // ThreadHelper.ThrowIfNotOnUIThread();
  286. // try
  287. // {
  288. // if (Dte != null)
  289. // {
  290. // foreach (EnvDTE.Project item in Dte.Solution.Projects)
  291. // {
  292. // if (item.Name == projectName)
  293. // {
  294. // foreach (string file in files)
  295. // {
  296. // Dte.StatusBar.Text = $"VberCode:添加文件[{file}]...";
  297. // item.ProjectItems.AddFromFile(file);
  298. // }
  299. // item.Save();
  300. // break;
  301. // }
  302. // if (item.ProjectItems != null)
  303. // {
  304. // foreach (ProjectItem childItem in item.ProjectItems)
  305. // {
  306. // if (childItem.Name == projectName)
  307. // {
  308. // foreach (string file in files)
  309. // {
  310. // Dte.StatusBar.Text = $"VberCode:添加文件[{file}]...";
  311. // childItem.SubProject?.ProjectItems?.AddFromFile(file);
  312. // }
  313. // childItem.SubProject?.Save();
  314. // break;
  315. // }
  316. // }
  317. // }
  318. // }
  319. // }
  320. // }
  321. // catch
  322. // {
  323. // //ignored
  324. // //Debug.WriteLine(e);
  325. // }
  326. //}
  327. #endregion 创建文件
  328. }
  329. }