CSharpCommonTableGenerater.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. namespace etoy
  2. {
  3. class CSharpCommonTableGenerater : IGenerater
  4. {
  5. private const string CLASS_TAIL = "Table"; // C# Table作为类型后缀
  6. private const string RELATIVE_PATH = "Tables";
  7. public void Generate(Context context)
  8. {
  9. var tables = context.Blackboard.Tables;
  10. foreach (var table in tables)
  11. {
  12. if (table.TableTag.HasFlag(TableTag.Client))
  13. {
  14. GenSingle(context, table);
  15. GenEnum(context, table);
  16. }
  17. }
  18. }
  19. private void GenSingle(Context context, Table table)
  20. {
  21. string fileName = table.Name + $"{CLASS_TAIL}.cs";
  22. string directory = Path.Combine(context.Option.ClientCodeOutput, RELATIVE_PATH).ToPath();
  23. if (!Directory.Exists(directory))
  24. Directory.CreateDirectory(directory);
  25. string path = Path.Combine(directory, fileName);
  26. var serializes = new List<string>(); //序列化属性
  27. var deserializes = new List<string>(); //反序列化属性
  28. using var writer = new CodeWriter(path);
  29. writer.WriteLine("// Generate By EToy");
  30. writer.WriteLine("// Don't Edit It!!");
  31. writer.WriteLine();
  32. writer.WriteLine("using XGame.Framework.Database;");
  33. writer.WriteLine("using XGame.Framework.Serialization;");
  34. writer.WriteLine();
  35. // namespace
  36. writer.Bracket("namespace XGame.Database");
  37. {
  38. // class
  39. writer.Summary(table.Description);
  40. writer.Bracket($"public sealed class {table.Name}{CLASS_TAIL} : ITable");
  41. {
  42. var pkFieldInfo = table.GetPKFieldInfo();
  43. if (pkFieldInfo != null)
  44. {
  45. writer.WriteLine($"long ITable.Key => {pkFieldInfo.FieldName.ToTitleCase()};");
  46. }
  47. else
  48. {
  49. throw new Exception($"配置表生成CSharp代码, 表结构未设置PrimaryKey的字段. {table.Path}");
  50. }
  51. // 属性定义
  52. for (int i = 0, length = table.FieldInfos.Length; i < length; i++)
  53. {
  54. var fieldInfo = table.FieldInfos[i];
  55. // no export server’s field
  56. if (!fieldInfo.IsClientField)
  57. continue;
  58. writer.WriteLine();
  59. writer.Summary(fieldInfo.Description);
  60. string notes = string.IsNullOrEmpty(fieldInfo.Tags) ? string.Empty : $" // {fieldInfo.Tags}";
  61. string fieldType = fieldInfo.FieldType;// isContainsMetadataType ? $"{fieldInfo.FieldType}{STRUCT_TAIL}" : fieldInfo.FieldType;
  62. //bool isContainsMetadataType = context.Blackboard.ContainsMetadataType(fieldType);
  63. var fieldName = fieldInfo.FieldName.ToTitleCase();
  64. if (fieldInfo.IsRepeated)
  65. {
  66. // 数组
  67. writer.WriteLine($"public {fieldType}[] {fieldName} {{ get; private set; }}{notes}");
  68. deserializes.Add($"{fieldName} = reader.ReadEnumerable<{fieldType}[]>();");
  69. serializes.Add($"writer.Write({fieldName});");
  70. }
  71. else
  72. { // 字段
  73. writer.WriteLine($"public {fieldType} {fieldName} {{ get; private set; }}{notes}");
  74. if (context.Blackboard.TryGetMetadata(fieldType, out var metadata))
  75. {
  76. if (metadata.StructType == MetadataStructType.Enum)
  77. {// 枚举
  78. deserializes.Add($"{fieldName} = ({fieldType})reader.ReadInt();");
  79. serializes.Add($"writer.Write((int){fieldName});");
  80. }
  81. else
  82. { // 数据结构
  83. deserializes.Add($"{fieldName} = reader.ReadSerializable<{fieldType}>();");
  84. serializes.Add($"writer.Write({fieldName});");
  85. }
  86. }
  87. else
  88. { // 普通字段
  89. deserializes.Add($"{fieldName} = reader.Read{fieldType.ToTitleCase()}();");
  90. serializes.Add($"writer.Write({fieldName});");
  91. }
  92. }
  93. }
  94. // 反序列化数据
  95. writer.WriteLine();
  96. writer.Bracket("void ISerializable.Deserialize(IReader reader)");
  97. {
  98. for (var i = 0; i < deserializes.Count; i++)
  99. {
  100. writer.WriteLine(deserializes[i]);
  101. }
  102. }
  103. writer.EndBracket();
  104. // 序列化数据
  105. writer.WriteLine();
  106. writer.Bracket("void ISerializable.Serialize(IWriter writer)");
  107. {
  108. for(var i = 0;i < serializes.Count;i++)
  109. {
  110. writer.WriteLine(serializes[i]);
  111. }
  112. }
  113. writer.EndBracket();
  114. }
  115. writer.EndBracket();
  116. }
  117. writer.EndBracket();
  118. //writer.Flush();
  119. }
  120. /// <summary>
  121. /// 生成配置表的枚举
  122. /// </summary>
  123. /// <param name="context"></param>
  124. /// <param name="table"></param>
  125. private void GenEnum(Context context, Table table)
  126. {
  127. if (table.tableEnum == null)
  128. return;
  129. var enumName = table.tableEnum.name;
  130. var filePath = $"{context.Option.ClientCodeOutput}/{enumName}.cs";
  131. using var writer = new CodeWriter(filePath);
  132. writer.WriteLine("// Generate By EToy");
  133. writer.WriteLine("// Don't Edit It!!");
  134. writer.WriteLine();
  135. writer.Bracket("namespace XGame.Database");
  136. {
  137. writer.Summary($"{table.Name} 转枚举 {enumName}\nKey : {table.tableEnum.key} \nValue :{table.tableEnum.value}");
  138. writer.Bracket($"public enum {enumName} : int");
  139. {
  140. for (int i = 0, rowCount = table.Rows.Count; i < rowCount; i++)
  141. {
  142. var row = table.Rows[i];
  143. GetEnumProperty(row, table.tableEnum, out var name, out var value, out var summary);
  144. if (string.IsNullOrEmpty(name)) continue;
  145. writer.Summary(summary);
  146. writer.WriteLine($"{name} = {value},");
  147. }
  148. writer.EndBracket();
  149. }
  150. writer.EndBracket();
  151. }
  152. }
  153. private void GetEnumProperty(Row row, TableEnum @enum, out string name, out string value, out string summary)
  154. {
  155. name = value = summary = string.Empty;
  156. foreach (var cell in row.Cells)
  157. {
  158. if (@enum.key.Equals(cell.FieldInfo.FieldName, StringComparison.OrdinalIgnoreCase))
  159. {
  160. name = cell.Value.ToTitleCase();
  161. }
  162. else if (@enum.value.Equals(cell.FieldInfo.FieldName, StringComparison.OrdinalIgnoreCase))
  163. {
  164. value = cell.Value;
  165. }
  166. else if (@enum.summary.Equals(cell.FieldInfo.FieldName, StringComparison.OrdinalIgnoreCase))
  167. {
  168. summary = cell.Value;
  169. }
  170. }
  171. }
  172. }
  173. }