namespace etoy { class CSharpMetadataTableGenerater : IGenerater { private const string RELATIVE_PATH = "Metadatas"; public void Generate(Context context) { var tables = context.Blackboard.MetadataTables; foreach (var table in tables) GenSingle(table, context); } private void GenSingle(MetadataTable table, Context context) { string directory = Path.Combine(context.Option.ClientCodeOutput, RELATIVE_PATH).ToPath(); if (!Directory.Exists(directory)) Directory.CreateDirectory(directory); foreach (var row in table.Rows) { var key = row.Struct.StructType; switch (key) { case MetadataStructType.Struct: GenStruct(context, row, directory); break; case MetadataStructType.Enum: GenEnum(row, directory); break; } } } private void GenStruct(Context context, MetadataRow row, string directory) { string csharpTypeName = row.Struct.Name; string fileName = csharpTypeName + ".cs"; string path = Path.Combine(directory, fileName); var serializes = new List(); //序列化属性 var deserializes = new List(); //反序列化属性 using var writer = new CodeWriter(path); writer.WriteLine("// Generate By EToy"); writer.WriteLine("// Don't Edit It!!"); writer.WriteLine(); writer.WriteLine("using XGame.Framework.Serialization;"); // namespace writer.Bracket("namespace XGame.Database"); { // class writer.WriteLine("/// "); writer.WriteLine($"/// {row.Struct.Description}"); writer.WriteLine("/// "); writer.Bracket($"public sealed class {csharpTypeName} : ISerializable"); { // 属性定义 foreach (var field in row.Struct.Fields) { //string repeated = field.StructRepeated ? "[]" : string.Empty; //bool isContainsMetadataType = context.Blackboard.ContainsMetadataType(field.FieldType); string fieldType = field.FieldType;// isContainsMetadataType ? $"{field.FieldType}" : field.FieldType; var fieldName = field.Name.ToTitleCase(); if (field.StructRepeated) { // 数组 writer.WriteLine($"public {fieldType}[] {fieldName} {{ get; private set; }}"); deserializes.Add($"{fieldName} = reader.ReadEnumerable<{fieldType}[]>();"); serializes.Add($"writer.Write({fieldName});"); } else { // 字段 writer.WriteLine($"public {fieldType} {fieldName} {{ get; private set; }}"); if (context.Blackboard.TryGetMetadata(fieldType, out var metadata)) { if (metadata.StructType == MetadataStructType.Enum) {// 枚举 deserializes.Add($"{fieldName} = ({fieldType})reader.ReadInt();"); serializes.Add($"writer.Write((int){fieldName});"); } else { // 数据结构 deserializes.Add($"{fieldName} = reader.ReadSerializable<{fieldType}>();"); serializes.Add($"writer.Write({fieldName});"); } } else { // 普通字段 deserializes.Add($"{fieldName} = reader.Read{fieldType.ToTitleCase()}();"); serializes.Add($"writer.Write({fieldName});"); } } } // 反序列化数据 writer.WriteLine(); writer.Bracket("void ISerializable.Deserialize(IReader reader)"); { for (var i = 0; i < deserializes.Count; i++) { writer.WriteLine(deserializes[i]); } } writer.EndBracket(); // 序列化数据 writer.WriteLine(); writer.Bracket("void ISerializable.Serialize(IWriter writer)"); { for (var i = 0; i < serializes.Count; i++) { writer.WriteLine(serializes[i]); } } writer.EndBracket(); } writer.EndBracket(); } writer.EndBracket(); } private void GenEnum(MetadataRow row, string directory) { string csharpTypeName = row.Struct.Name; string fileName = csharpTypeName + ".cs"; string path = Path.Combine(directory, fileName); using CodeWriter writer = new CodeWriter(path); // namespace writer.WriteLine("// Generate By EToy"); writer.WriteLine("// Don't Edit It!!"); writer.WriteLine(); writer.Bracket("namespace XGame.Database"); { // enum writer.WriteLine("/// "); writer.WriteLine($"/// {row.Struct.Description}"); writer.WriteLine("/// "); writer.Bracket($"public enum {csharpTypeName} : int"); { foreach (var field in row.Struct.Fields) { if (string.IsNullOrEmpty(field.EnumValue)) writer.WriteLine($"{field.Name},"); else writer.WriteLine($"{field.Name} = {field.EnumValue},"); } writer.EndBracket(); } writer.EndBracket(); } } } }