Newer
Older
DungeonShooting / DungeonShooting_Godot / excelTool / ExcelGenerator.cs
@小李xl 小李xl on 26 Feb 2024 31 KB 制作大厅物体中
  1.  
  2. using System.Text.Json;
  3. using System.Text.RegularExpressions;
  4. using Aspose.Cells;
  5. using Environment = System.Environment;
  6.  
  7. public static class ExcelGenerator
  8. {
  9. private static HashSet<string> _excelNames = new HashSet<string>();
  10. private enum CollectionsType
  11. {
  12. None,
  13. Array,
  14. Map
  15. }
  16. private class MappingData
  17. {
  18. public string TypeStr;
  19. public string TypeName;
  20. public CollectionsType CollectionsType;
  21. public bool IsRefExcel;
  22. public string RefTypeStr;
  23. public string RefTypeName;
  24.  
  25. public MappingData(string typeStr, string typeName, CollectionsType collectionsType)
  26. {
  27. TypeStr = typeStr;
  28. TypeName = typeName;
  29. CollectionsType = collectionsType;
  30. IsRefExcel = false;
  31. }
  32. public MappingData(string typeStr, string typeName, CollectionsType collectionsType, string refTypeStr, string refTypeName)
  33. {
  34. TypeStr = typeStr;
  35. TypeName = typeName;
  36. CollectionsType = collectionsType;
  37. IsRefExcel = true;
  38. RefTypeStr = refTypeStr;
  39. RefTypeName = refTypeName;
  40. }
  41. }
  42.  
  43. private class ExcelData
  44. {
  45. public string TableName;
  46. public string OutCode;
  47. public List<string> ColumnNames = new List<string>();
  48. public Dictionary<string, MappingData> ColumnMappingData = new Dictionary<string, MappingData>();
  49. public Dictionary<string, Type> ColumnType = new Dictionary<string, Type>();
  50. public List<Dictionary<string, object>> DataList = new List<Dictionary<string, object>>();
  51. }
  52. /// <summary>
  53. /// 导出 Excel 表
  54. /// </summary>
  55. public static bool ExportExcel()
  56. {
  57. var excelPath = "excel/";
  58. var jsonPath = "config/";
  59. var codePath = "src/";
  60. return ExportExcel(excelPath, jsonPath, codePath);
  61. }
  62. /// <summary>
  63. /// 导出 Excel 表
  64. /// </summary>
  65. /// <param name="excelFilePath">excel文件路径</param>
  66. /// <param name="jsonOutPath">json配置输出路径</param>
  67. /// <param name="codeOutPath">代码输出路径</param>
  68. public static bool ExportExcel(string excelFilePath, string jsonOutPath, string codeOutPath)
  69. {
  70. _excelNames.Clear();
  71. Console.WriteLine("当前路径: " + Environment.CurrentDirectory);
  72. Console.WriteLine("excel路径: " + excelFilePath);
  73. Console.WriteLine("json输出路径: " + jsonOutPath);
  74. Console.WriteLine("cs代码输出路径: " + codeOutPath);
  75. try
  76. {
  77. var excelDataList = new List<ExcelData>();
  78. var directoryInfo = new DirectoryInfo(excelFilePath);
  79. if (directoryInfo.Exists)
  80. {
  81. var fileInfos = directoryInfo.GetFiles();
  82. //记录文件
  83. foreach (var fileInfo in fileInfos)
  84. {
  85. if (fileInfo.Extension == ".xlsx")
  86. {
  87. var fileName = Path.GetFileNameWithoutExtension(fileInfo.Name).FirstToUpper();
  88. _excelNames.Add(fileName);
  89. }
  90. }
  91.  
  92. //读取配置文件
  93. foreach (var fileInfo in fileInfos)
  94. {
  95. if (fileInfo.Extension == ".xlsx")
  96. {
  97. if (fileInfo.Name == "ExcelConfig.xlsx")
  98. {
  99. throw new Exception("excel表文件名称不允许叫'ExcelConfig.xlsx'!");
  100. }
  101. Console.WriteLine("excel表: " + fileInfo.FullName);
  102. excelDataList.Add(ReadExcel(fileInfo.FullName));
  103. }
  104. }
  105. }
  106.  
  107. Console.WriteLine($"一共检测到excel表共{excelDataList.Count}张.");
  108. if (excelDataList.Count == 0)
  109. {
  110. return true;
  111. }
  112. if (Directory.Exists(codeOutPath))
  113. {
  114. Directory.Delete(codeOutPath, true);
  115. }
  116. if (Directory.Exists(jsonOutPath))
  117. {
  118. Directory.Delete(jsonOutPath, true);
  119. }
  120. Directory.CreateDirectory(codeOutPath);
  121. Directory.CreateDirectory(jsonOutPath);
  122. //保存配置和代码
  123. foreach (var excelData in excelDataList)
  124. {
  125. File.WriteAllText(codeOutPath + "ExcelConfig_" + excelData.TableName + ".cs", excelData.OutCode);
  126. var config = new JsonSerializerOptions();
  127. config.WriteIndented = true;
  128. File.WriteAllText(jsonOutPath + excelData.TableName + ".json", JsonSerializer.Serialize(excelData.DataList, config));
  129. }
  130. //生成加载代码
  131. var code = GeneratorInitCode(excelDataList);
  132. File.WriteAllText(codeOutPath + "ExcelConfig.cs", code);
  133. }
  134. catch (Exception e)
  135. {
  136. PrintError(e.ToString());
  137. return false;
  138. }
  139.  
  140. return true;
  141. }
  142.  
  143. private static string GeneratorInitCode(List<ExcelData> excelList)
  144. {
  145. var code = $"using System;\n";
  146. code += $"using System.Collections.Generic;\n";
  147. code += $"using System.Text.Json;\n";
  148. code += $"using Godot;\n";
  149. code += $"\n";
  150. code += $"namespace Config;\n";
  151. code += $"\n";
  152. code += $"public static partial class ExcelConfig\n";
  153. code += $"{{\n";
  154.  
  155. var fieldCode = "";
  156. var callFuncCode = "";
  157. var callInitRefFuncCode = "";
  158. var funcCode = "";
  159. var initRefFuncCode = "";
  160. foreach (var excelData in excelList)
  161. {
  162. var idName = excelData.ColumnNames[0];
  163. var idTypeStr = excelData.ColumnMappingData[idName].TypeStr;
  164. //---------------------------- 引用其他表处理 ----------------------------
  165. var hasRefColumn = false;
  166. var refColumnNoneCode = "";
  167. foreach (var columnName in excelData.ColumnNames)
  168. {
  169. var mappingData = excelData.ColumnMappingData[columnName];
  170. if (mappingData.IsRefExcel)
  171. {
  172. hasRefColumn = true;
  173. if (mappingData.CollectionsType == CollectionsType.None)
  174. {
  175. refColumnNoneCode += $" if (!string.IsNullOrEmpty(item.__{columnName}))\n";
  176. refColumnNoneCode += $" {{\n";
  177. refColumnNoneCode += $" item.{columnName} = {mappingData.RefTypeName}_Map[item.__{columnName}];\n";
  178. refColumnNoneCode += $" }}\n";
  179. }
  180. else if (mappingData.CollectionsType == CollectionsType.Array)
  181. {
  182. refColumnNoneCode += $" if (item.__{columnName} != null)\n";
  183. refColumnNoneCode += $" {{\n";
  184. refColumnNoneCode += $" item.{columnName} = new {mappingData.RefTypeName}[item.__{columnName}.Length];\n";
  185. refColumnNoneCode += $" for (var i = 0; i < item.__{columnName}.Length; i++)\n";
  186. refColumnNoneCode += $" {{\n";
  187. refColumnNoneCode += $" item.{columnName}[i] = {mappingData.RefTypeName}_Map[item.__{columnName}[i]];\n";
  188. refColumnNoneCode += $" }}\n";
  189. refColumnNoneCode += $" }}\n";
  190. }
  191. else
  192. {
  193. refColumnNoneCode += $" if (item.__{columnName} != null)\n";
  194. refColumnNoneCode += $" {{\n";
  195. refColumnNoneCode += $" item.{columnName} = new {mappingData.RefTypeStr}();\n";
  196. refColumnNoneCode += $" foreach (var pair in item.__{columnName})\n";
  197. refColumnNoneCode += $" {{\n";
  198. refColumnNoneCode += $" item.{columnName}.Add(pair.Key, {mappingData.RefTypeName}_Map[pair.Value]);\n";
  199. refColumnNoneCode += $" }}\n";
  200. refColumnNoneCode += $" }}\n";
  201. }
  202. refColumnNoneCode += $"\n";
  203. }
  204. }
  205. //----------------------------- 数据集合 ------------------------------------
  206. fieldCode += $" /// <summary>\n";
  207. fieldCode += $" /// {excelData.TableName}.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同\n";
  208. fieldCode += $" /// </summary>\n";
  209. fieldCode += $" public static List<{excelData.TableName}> {excelData.TableName}_List {{ get; private set; }}\n";
  210. fieldCode += $" /// <summary>\n";
  211. fieldCode += $" /// {excelData.TableName}.xlsx表数据集合, 里 Map 形式存储, key 为 {idName}\n";
  212. fieldCode += $" /// </summary>\n";
  213. fieldCode += $" public static Dictionary<{idTypeStr}, {excelData.TableName}> {excelData.TableName}_Map {{ get; private set; }}\n";
  214. fieldCode += $"\n";
  215. //------------------------------- 初始化函数 -------------------------------------
  216. callFuncCode += $" _Init{excelData.TableName}Config();\n";
  217. funcCode += $" private static void _Init{excelData.TableName}Config()\n";
  218. funcCode += $" {{\n";
  219. funcCode += $" try\n";
  220. funcCode += $" {{\n";
  221. funcCode += $" var text = _ReadConfigAsText(\"res://resource/config/{excelData.TableName}.json\");\n";
  222. if (hasRefColumn) //存在引用列
  223. {
  224. funcCode += $" {excelData.TableName}_List = new List<{excelData.TableName}>(JsonSerializer.Deserialize<List<Ref_{excelData.TableName}>>(text));\n";
  225. }
  226. else
  227. {
  228. funcCode += $" {excelData.TableName}_List = JsonSerializer.Deserialize<List<{excelData.TableName}>>(text);\n";
  229. }
  230. funcCode += $" {excelData.TableName}_Map = new Dictionary<{idTypeStr}, {excelData.TableName}>();\n";
  231. funcCode += $" foreach (var item in {excelData.TableName}_List)\n";
  232. funcCode += $" {{\n";
  233. funcCode += $" {excelData.TableName}_Map.Add(item.{idName}, item);\n";
  234. funcCode += $" }}\n";
  235. funcCode += $" }}\n";
  236. funcCode += $" catch (Exception e)\n";
  237. funcCode += $" {{\n";
  238. funcCode += $" GD.PrintErr(e.ToString());\n";
  239. funcCode += $" throw new Exception(\"初始化表'{excelData.TableName}'失败!\");\n";
  240. funcCode += $" }}\n";
  241. funcCode += $" }}\n";
  242.  
  243. //------------------------------- 初始化引用 ---------------------------------
  244. if (hasRefColumn)
  245. {
  246. callInitRefFuncCode += $" _Init{excelData.TableName}Ref();\n";
  247.  
  248. initRefFuncCode += $" private static void _Init{excelData.TableName}Ref()\n";
  249. initRefFuncCode += $" {{\n";
  250. initRefFuncCode += $" foreach (Ref_{excelData.TableName} item in {excelData.TableName}_List)\n";
  251. initRefFuncCode += $" {{\n";
  252. initRefFuncCode += $" try\n";
  253. initRefFuncCode += $" {{\n";
  254. initRefFuncCode += refColumnNoneCode;
  255. initRefFuncCode += $" }}\n";
  256. initRefFuncCode += $" catch (Exception e)\n";
  257. initRefFuncCode += $" {{\n";
  258. initRefFuncCode += $" GD.PrintErr(e.ToString());\n";
  259. initRefFuncCode += $" throw new Exception(\"初始化'{excelData.TableName}'引用其他表数据失败, 当前行id: \" + item.Id);\n";
  260. initRefFuncCode += $" }}\n";
  261. initRefFuncCode += $" }}\n";
  262. initRefFuncCode += $" }}\n";
  263. }
  264. }
  265.  
  266. code += fieldCode;
  267. code += $"\n";
  268. code += $" private static bool _init = false;\n";
  269. code += $" /// <summary>\n";
  270. code += $" /// 初始化所有配置表数据\n";
  271. code += $" /// </summary>\n";
  272. code += $" public static void Init()\n";
  273. code += $" {{\n";
  274. code += $" if (_init) return;\n";
  275. code += $" _init = true;\n";
  276. code += $"\n";
  277. code += callFuncCode;
  278. code += $"\n";
  279. code += callInitRefFuncCode;
  280. code += $" }}\n";
  281. code += funcCode;
  282. code += $"\n";
  283. code += initRefFuncCode;
  284. code += $" private static string _ReadConfigAsText(string path)\n";
  285. code += $" {{\n";
  286. code += $" var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);\n";
  287. code += $" var asText = file.GetAsText();\n";
  288. code += $" file.Dispose();\n";
  289. code += $" return asText;\n";
  290. code += $" }}\n";
  291. code += $"}}";
  292. return code;
  293. }
  294. private static ExcelData ReadExcel(string excelPath)
  295. {
  296. var excelData = new ExcelData();
  297. //文件名称
  298. var fileName = Path.GetFileNameWithoutExtension(excelPath).FirstToUpper();
  299. excelData.TableName = fileName;
  300. //输出代码
  301. var outStr = $"using System.Text.Json.Serialization;\n";
  302. outStr += $"using System.Collections.Generic;\n\n";
  303. outStr += $"namespace Config;\n\n";
  304. outStr += $"public static partial class ExcelConfig\n{{\n";
  305. outStr += $" public class {fileName}\n";
  306. outStr += $" {{\n";
  307. //继承的带有引用其他表的类代码
  308. var outRefStr = "";
  309. var cloneFuncStr = $" /// <summary>\n";
  310. cloneFuncStr += $" /// 返回浅拷贝出的新对象\n";
  311. cloneFuncStr += $" /// </summary>\n";
  312. cloneFuncStr += $" public {fileName} Clone()\n";
  313. cloneFuncStr += $" {{\n";
  314. cloneFuncStr += $" var inst = new {fileName}();\n";
  315. var sourceFile = excelPath;
  316. //列数
  317. var columnCount = -1;
  318. //加载表数据
  319. var workbook = new Workbook(sourceFile);
  320. using (workbook)
  321. {
  322. var sheet1 = workbook.Worksheets[0];
  323. var cells = sheet1.Cells;
  324. //先解析表中的列名, 注释, 类型
  325. var names = cells.Rows[0];
  326. var descriptions = cells.Rows[1];
  327. var types = cells.Rows[2];
  328.  
  329. columnCount = 0;
  330. foreach (Cell cell in names)
  331. {
  332. //字段名称
  333. var field = GetCellStringValue(cell);
  334. if (string.IsNullOrEmpty(field))
  335. {
  336. if (cell.Column == 0)
  337. {
  338. throw new Exception($"表'{fileName}'的列数为0!");
  339. }
  340. //到达最后一列了
  341. break;
  342. }
  343.  
  344. columnCount++;
  345. field = field.FirstToUpper();
  346. excelData.ColumnNames.Add(field);
  347. if (field == "Clone")
  348. {
  349. throw new Exception($"表'{fileName}'中不允许有'Clone'字段!");
  350. }
  351.  
  352. var descriptionCell = descriptions[cell.Column];
  353. //描述
  354. string description;
  355. if (descriptionCell != null)
  356. {
  357. description = GetCellStringValue(descriptionCell).Replace("\n", " <br/>\n /// ");
  358. }
  359. else
  360. {
  361. description = "";
  362. }
  363. //类型
  364. var typeString = GetCellStringValue(types[cell.Column]);
  365. if (string.IsNullOrEmpty(typeString))
  366. {
  367. throw new Exception($"表'{fileName}'中'{field}'这一列类型为空!");
  368. }
  369. //尝试解析类型
  370. MappingData mappingData;
  371. try
  372. {
  373. mappingData = ConvertToType(typeString.Replace(" ", ""));
  374. }
  375. catch (Exception e)
  376. {
  377. PrintError(e.ToString());
  378. throw new Exception($"表'{fileName}'中'{field}'这一列类型描述语法错误: {typeString}");
  379. }
  380. if (!excelData.ColumnMappingData.TryAdd(field, mappingData))
  381. {
  382. throw new Exception($"表'{fileName}'中存在相同名称的列: '{field}'!");
  383. }
  384. outStr += $" /// <summary>\n";
  385. outStr += $" /// {description}\n";
  386. outStr += $" /// </summary>\n";
  387. if (!mappingData.IsRefExcel) //没有引用其他表
  388. {
  389. outStr += $" [JsonInclude]\n";
  390. outStr += $" public {mappingData.TypeStr} {field};\n\n";
  391. }
  392. else
  393. {
  394. outStr += $" public {mappingData.RefTypeStr} {field};\n\n";
  395. }
  396.  
  397. if (mappingData.IsRefExcel) //引用其他表
  398. {
  399. if (string.IsNullOrEmpty(outRefStr))
  400. {
  401. outRefStr += $" private class Ref_{fileName} : {fileName}\n";
  402. outRefStr += $" {{\n";
  403. }
  404. outRefStr += $" [JsonInclude]\n";
  405. outRefStr += $" public {mappingData.TypeStr} __{field};\n\n";
  406. }
  407. cloneFuncStr += $" inst.{field} = {field};\n";
  408. }
  409. cloneFuncStr += " return inst;\n";
  410. cloneFuncStr += " }\n";
  411. outStr += cloneFuncStr;
  412. outStr += " }\n";
  413.  
  414. if (!string.IsNullOrEmpty(outRefStr))
  415. {
  416. outRefStr += " }\n";
  417. outStr += outRefStr;
  418. }
  419. outStr += "}";
  420. //解析字段类型
  421. foreach (var kv in excelData.ColumnMappingData)
  422. {
  423. var typeName = kv.Value.TypeName;
  424. var type = Type.GetType(typeName);
  425. if (type == null)
  426. {
  427. throw new Exception($"表'{fileName}'中'{kv.Key}'这一列类型未知! " + kv.Value.TypeStr);
  428. }
  429. excelData.ColumnType.Add(kv.Key, type);
  430. }
  431.  
  432. //解析数据
  433. foreach (Row row in cells.Rows)
  434. {
  435. if (row == null || row.Index < 3)
  436. {
  437. continue;
  438. }
  439. Dictionary<string, object> data = null;
  440. for (int j = 0; j < columnCount; j++)
  441. {
  442. var cell = row[j];
  443. var strValue = GetCellStringValue(cell);
  444. //如果这一行的第一列数据为空, 则跳过这一行
  445. if (j == 0 && string.IsNullOrEmpty(strValue))
  446. {
  447. break;
  448. }
  449. else if (data == null)
  450. {
  451. data = new Dictionary<string, object>();
  452. excelData.DataList.Add(data);
  453. }
  454.  
  455. var fieldName = excelData.ColumnNames[j];
  456. var mappingData = excelData.ColumnMappingData[fieldName];
  457. var field = mappingData.IsRefExcel ? "__" + fieldName : fieldName;
  458. try
  459. {
  460. switch (mappingData.TypeStr)
  461. {
  462. case "bool":
  463. case "boolean":
  464. data.Add(field, GetCellBooleanValue(cell));
  465. break;
  466. case "byte":
  467. data.Add(field, Convert.ToByte(GetCellNumberValue(cell)));
  468. break;
  469. case "sbyte":
  470. data.Add(field, Convert.ToSByte(GetCellNumberValue(cell)));
  471. break;
  472. case "short":
  473. data.Add(field, Convert.ToInt16(GetCellNumberValue(cell)));
  474. break;
  475. case "ushort":
  476. data.Add(field, Convert.ToUInt16(GetCellNumberValue(cell)));
  477. break;
  478. case "int":
  479. data.Add(field, Convert.ToInt32(GetCellNumberValue(cell)));
  480. break;
  481. case "uint":
  482. data.Add(field, Convert.ToUInt32(GetCellNumberValue(cell)));
  483. break;
  484. case "long":
  485. data.Add(field, Convert.ToInt64(GetCellNumberValue(cell)));
  486. break;
  487. case "ulong":
  488. data.Add(field, Convert.ToUInt64(GetCellNumberValue(cell)));
  489. break;
  490. case "float":
  491. data.Add(field, Convert.ToSingle(GetCellNumberValue(cell)));
  492. break;
  493. case "double":
  494. data.Add(field, GetCellNumberValue(cell));
  495. break;
  496. case "string":
  497. data.Add(field, GetCellStringValue(cell));
  498. break;
  499. default:
  500. {
  501. var cellStringValue = GetCellStringValue(cell);
  502. if (cellStringValue.Length == 0)
  503. {
  504. if (mappingData.TypeStr == nameof(ActivityQuality))
  505. {
  506. ActivityQuality v = default;
  507. data.Add(field, v);
  508. }
  509. else if (mappingData.TypeStr == nameof(ActivityType))
  510. {
  511. ActivityType v = default;
  512. data.Add(field, v);
  513. }
  514. else
  515. {
  516. data.Add(field, null);
  517. }
  518. }
  519. else
  520. {
  521. data.Add(field, JsonSerializer.Deserialize(cellStringValue, excelData.ColumnType[fieldName]));
  522. }
  523. }
  524. break;
  525. }
  526. }
  527. catch (Exception e)
  528. {
  529. PrintError(e.ToString());
  530. throw new Exception($"解析表'{fileName}'第'{row.Index + 1}'行第'{j + 1}'列数据时发生异常");
  531. }
  532. }
  533. }
  534. }
  535.  
  536. excelData.OutCode = outStr;
  537. return excelData;
  538. }
  539.  
  540. private static string GetCellStringValue(Cell cell)
  541. {
  542. if (cell == null)
  543. {
  544. return "";
  545. }
  546. switch (cell.Type)
  547. {
  548. case CellValueType.IsNumeric:
  549. return cell.DoubleValue.ToString();
  550. case CellValueType.IsString:
  551. return cell.StringValue;
  552. case CellValueType.IsBool:
  553. return cell.BoolValue ? "true" : "false";
  554. }
  555.  
  556. return "";
  557. }
  558.  
  559. private static double GetCellNumberValue(Cell cell)
  560. {
  561. if (cell == null)
  562. {
  563. return 0;
  564. }
  565. switch (cell.Type)
  566. {
  567. case CellValueType.IsNumeric:
  568. return cell.DoubleValue;
  569. case CellValueType.IsString:
  570. return double.Parse(cell.StringValue);
  571. case CellValueType.IsBool:
  572. return cell.BoolValue ? 1 : 0;
  573. }
  574. return 0;
  575. }
  576.  
  577. private static bool GetCellBooleanValue(Cell cell)
  578. {
  579. if (cell == null)
  580. {
  581. return false;
  582. }
  583. switch (cell.Type)
  584. {
  585. case CellValueType.IsNumeric:
  586. return cell.DoubleValue != 0;
  587. case CellValueType.IsString:
  588. {
  589. var value = cell.StringValue;
  590. if (string.IsNullOrWhiteSpace(value))
  591. {
  592. return false;
  593. }
  594. return bool.Parse(value);
  595. }
  596. case CellValueType.IsBool:
  597. return cell.BoolValue;
  598. }
  599.  
  600. return false;
  601. }
  602.  
  603. private static MappingData ConvertToType(string str, int depth = 0)
  604. {
  605. if (Regex.IsMatch(str, "^\\w+$"))
  606. {
  607. var typeStr = TypeStrMapping(str);
  608. var typeName = TypeNameMapping(str);
  609. return new MappingData(typeStr, typeName, CollectionsType.None);
  610. }
  611. else if (Regex.IsMatch(str, "^\\$\\w+$")) //引用其他表
  612. {
  613. var realName = str.Substring(1);
  614. if (!_excelNames.Contains(realName))
  615. {
  616. throw new Exception($"引用表数据失败, 未找到表: {realName}!");
  617. }
  618.  
  619. if (depth > 1)
  620. {
  621. throw new Exception("引用表数据失败, 引用表数据仅支持放入第一层的数组和字典!");
  622. }
  623.  
  624. return new MappingData(TypeStrMapping("string"), TypeNameMapping("string"), CollectionsType.None, realName, realName);
  625. }
  626. else if (str.StartsWith('{')) //字典
  627. {
  628. var tempStr = str.Substring(1, str.Length - 2);
  629. var index = tempStr.IndexOf(':');
  630. if (index == -1)
  631. {
  632. throw new Exception("类型描述语法错误!");
  633. }
  634.  
  635. var keyStr = tempStr.Substring(0, index);
  636. if (!IsBaseType(keyStr))
  637. {
  638. throw new Exception($"字典key类型必须是基础类型!");
  639. }
  640.  
  641. var type1 = ConvertToType(keyStr, depth + 1);
  642. var type2 = ConvertToType(tempStr.Substring(index + 1), depth + 1);
  643.  
  644. var typeStr = $"Dictionary<{type1.TypeStr}, {type2.TypeStr}>";
  645. var typeName = $"System.Collections.Generic.Dictionary`2[[{type1.TypeName}],[{type2.TypeName}]]";
  646.  
  647. if (type2.IsRefExcel) //引用过其他表
  648. {
  649. var refTypeStr = $"Dictionary<{type1.TypeStr}, {type2.RefTypeStr}>";
  650. return new MappingData(typeStr, typeName, CollectionsType.Map, refTypeStr, type2.RefTypeName);
  651. }
  652.  
  653. return new MappingData(typeStr, typeName, CollectionsType.Map);
  654. }
  655. else if (str.StartsWith('[')) //数组
  656. {
  657. var tempStr = str.Substring(1, str.Length - 2);
  658. var typeData = ConvertToType(tempStr, depth + 1);
  659. var typeStr = typeData.TypeStr + "[]";
  660. var typeName = typeData.TypeName + "[]";
  661.  
  662. if (typeData.IsRefExcel) //引用过其他表
  663. {
  664. var refTypeStr = typeData.RefTypeStr + "[]";
  665. return new MappingData(typeStr, typeName, CollectionsType.Array, refTypeStr, typeData.RefTypeName);
  666. }
  667. return new MappingData(typeStr, typeName, CollectionsType.Array);
  668. }
  669. throw new Exception("类型描述语法错误!");
  670. }
  671. private static string TypeStrMapping(string typeName)
  672. {
  673. switch (typeName)
  674. {
  675. case "boolean": return "bool";
  676. case "vector2": return "SerializeVector2";
  677. case "vector3": return "SerializeVector3";
  678. case "color": return "SerializeColor";
  679. case "activityType": return "ActivityType";
  680. case "activityQuality": return "ActivityQuality";
  681. }
  682.  
  683. return typeName;
  684. }
  685.  
  686. private static string TypeNameMapping(string typeName)
  687. {
  688. switch (typeName)
  689. {
  690. case "bool":
  691. case "boolean": return typeof(bool).FullName;
  692. case "byte": return typeof(byte).FullName;
  693. case "sbyte": return typeof(sbyte).FullName;
  694. case "short": return typeof(short).FullName;
  695. case "ushort": return typeof(ushort).FullName;
  696. case "int": return typeof(int).FullName;
  697. case "uint": return typeof(uint).FullName;
  698. case "long": return typeof(long).FullName;
  699. case "ulong": return typeof(ulong).FullName;
  700. case "string": return typeof(string).FullName;
  701. case "float": return typeof(float).FullName;
  702. case "double": return typeof(double).FullName;
  703. case "vector2": return "SerializeVector2";
  704. case "vector3": return "SerializeVector3";
  705. case "color": return "SerializeColor";
  706. case "activityType": return "ActivityType";
  707. case "activityQuality": return "ActivityQuality";
  708. }
  709.  
  710. return typeName;
  711. }
  712.  
  713. private static bool IsBaseType(string typeName)
  714. {
  715. switch (typeName)
  716. {
  717. case "bool":
  718. case "boolean":
  719. case "byte":
  720. case "sbyte":
  721. case "short":
  722. case "ushort":
  723. case "int":
  724. case "uint":
  725. case "long":
  726. case "ulong":
  727. case "string":
  728. case "float":
  729. case "double":
  730. return true;
  731. }
  732.  
  733. return false;
  734. }
  735. private static void PrintError(string message)
  736. {
  737. Console.ForegroundColor = ConsoleColor.Red;
  738. Console.WriteLine(message);
  739. Console.ResetColor();
  740. }
  741. /// <summary>
  742. /// 字符串首字母小写
  743. /// </summary>
  744. public static string FirstToLower(this string str)
  745. {
  746. return str.Substring(0, 1).ToLower() + str.Substring(1);
  747. }
  748. /// <summary>
  749. /// 字符串首字母大写
  750. /// </summary>
  751. public static string FirstToUpper(this string str)
  752. {
  753. return str.Substring(0, 1).ToUpper() + str.Substring(1);
  754. }
  755. }