using System; using System.IO; using System.Reflection; using System.Text; namespace StructToClass { class Program { private static string[] forVals = {"i", "j", "k", "m", "n", "x", "y", "z"}; private static string fileName = "../../../u2china_svr_proj/BattleServer/Src/ProtoHelper.cs"; private static FileStream fileStream = null; public enum ConvertMode { ClassToStruct = 1, StructToClass = 2, } private static void Write(string filename, string content) { fileStream.Write(ASCIIEncoding.Default.GetBytes(content)); //File.AppendAllText(filename, content); } private static void WriteLine(string filename, string content) { content += "\n"; fileStream.Write(ASCIIEncoding.Default.GetBytes(content)); //File.AppendAllText(filename, content); //File.AppendAllText(filename, "\n"); } private static void WriteIndent(int indentNum) { string str = null; for (int i = 0; i < indentNum; i++) { str += "\t"; } Write(fileName, str); } private static void WriteFileHead() { string str = @"// GENERATE BY TOOLS, DO NOT EDIT! namespace Battle { public static class ProtoHelper {"; WriteLine(fileName, str); } private static void WriteFileTail() { WriteLine(fileName, "\t}"); WriteLine(fileName, "}"); } private static void WriteFuncHead(Type clsType, ConvertMode mode) { if (mode == ConvertMode.ClassToStruct) { string str = $"\t\tpublic static void {clsType.Name}ToStruct(ProtoCSClass.{clsType.Name} cls, ref ProtoCSStruct.{clsType.Name} st)"; WriteLine(fileName, str); WriteLine(fileName, "\t\t{"); } else { string str = $"\t\tpublic static ProtoCSClass.{clsType.Name} {clsType.Name}ToClass(ref ProtoCSStruct.{clsType.Name} st)"; WriteLine(fileName, str); WriteLine(fileName, "\t\t{"); str = $"\t\t\tvar cls = new ProtoCSClass.{clsType.Name}();"; WriteLine(fileName, str); } } private static void WriteFuncTail(ConvertMode mode) { if (mode == ConvertMode.StructToClass) { WriteLine(fileName, "\t\t\treturn cls;"); } WriteLine(fileName, "\t\t}"); } public static void StructToClass(Type clsType, string prefix, int indentNum, int forIdx, ConvertMode convMode) { string src, dst, ns; if (convMode == ConvertMode.ClassToStruct) { src = "cls"; dst = "st"; ns = "ProtoCSStruct"; } else { src = "st"; dst = "cls"; ns = "ProtoCSClass"; } string newPrefix; var allFiled = clsType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); foreach (FieldInfo field in allFiled) { string line; var fieldType = field.FieldType; if (fieldType.IsEnum) { WriteIndent(indentNum); if (prefix != null) { line = $"{dst}.{prefix}.{field.Name} = ({ns}.{fieldType.Name}){src}.{prefix}.{field.Name};"; } else { line = $"{dst}.{field.Name} = ({ns}.{fieldType.Name}){src}.{field.Name};"; } WriteLine(fileName, line); } else if (fieldType.IsPrimitive) { WriteIndent(indentNum); if (prefix != null) { line = $"{dst}.{prefix}.{field.Name} = {src}.{prefix}.{field.Name};"; } else { line = $"{dst}.{field.Name} = {src}.{field.Name};"; } WriteLine(fileName, line); } else if (fieldType == typeof(string)) { WriteIndent(indentNum); if (convMode == ConvertMode.ClassToStruct) { if (prefix != null) { line = $"{dst}.{prefix}.{field.Name}.SetString({src}.{prefix}.{field.Name});"; } else { line = $"{dst}.{prefix}.SetString({src}.{prefix});"; } } else { if (prefix != null) { line = $"{dst}.{prefix}.{field.Name} = {src}.{prefix}.{field.Name}.GetString();"; } else { line = $"{dst}.{prefix} = {src}.{prefix}.GetString();"; } } WriteLine(fileName, line); } else if (fieldType.IsGenericType) { string fp = forVals[forIdx]; // class转struct传入引用ref, 数组先clear避免引入脏数据 if (convMode == ConvertMode.ClassToStruct) { WriteIndent(indentNum); if (prefix != null) { line = $"{dst}.{prefix}.{field.Name}.Clear();"; } else { line = $"{dst}.{field.Name}.Clear();"; } WriteLine(fileName, line); } WriteIndent(indentNum); if (prefix != null) { line = string.Format("for (int {0} = 0; {0} < {3}.{1}.{2}.Count; ++{0})", fp, prefix, field.Name, src); } else { line = string.Format("for (int {0} = 0; {0} < {2}.{1}.Count; ++{0})", fp, field.Name, src); } WriteLine(fileName, line); WriteIndent(indentNum); WriteLine(fileName, "{"); if (fieldType.GetGenericArguments()[0].IsPrimitive) { WriteIndent(indentNum + 1); if (prefix != null) { line = $"{dst}.{prefix}.{field.Name}.Add({src}.{prefix}.{field.Name}[{fp}]);"; } else { line = $"{dst}.{field.Name}.Add({src}.{field.Name}[{fp}]);"; } WriteLine(fileName, line); } else { string gname = fieldType.GetGenericArguments()[0].Name; WriteIndent(indentNum + 1); if (prefix != null) { line = $"{dst}.{prefix}.{field.Name}.Add(new {ns}.{gname}());"; } else { line = $"{dst}.{field.Name}.Add(new {ns}.{gname}());"; } WriteLine(fileName, line); if (prefix != null) { newPrefix = string.Format("{0}.{1}[{2}]", prefix, field.Name, fp); } else { newPrefix = string.Format("{0}[{1}]", field.Name, fp); } StructToClass(fieldType.GetGenericArguments()[0], newPrefix, indentNum + 1, forIdx + 1, convMode); } WriteIndent(indentNum); WriteLine(fileName, "}"); } else if (fieldType.IsClass) { if (prefix != null) { newPrefix = $"{prefix}.{field.Name}"; } else { newPrefix = field.Name; } StructToClass(fieldType, newPrefix, indentNum, forIdx, convMode); } } } static void Main(string[] args) { string path = "./config"; if (! File.Exists(path)) { Console.WriteLine("path {0} not exist", path); return; } var lines = File.ReadAllLines(path); if (lines.Length <= 0) { Console.WriteLine("config {0} no content", path); return; } if (File.Exists(fileName)) { Console.WriteLine(" {0} exist, delete it", fileName); File.Delete(fileName); } fileStream = new FileStream(fileName, FileMode.CreateNew); WriteFileHead(); foreach (string str in lines) { string name = str.Trim(); if (!string.IsNullOrEmpty(name)) { Type clsType = Type.GetType("ProtoCSClass." + name); WriteFuncHead(clsType, ConvertMode.ClassToStruct); StructToClass(clsType, null, 3, 0, ConvertMode.ClassToStruct); WriteFuncTail(ConvertMode.ClassToStruct); WriteLine(fileName, ""); WriteFuncHead(clsType, ConvertMode.StructToClass); StructToClass(clsType, null, 3, 0, ConvertMode.StructToClass); WriteFuncTail(ConvertMode.StructToClass); WriteLine(fileName, ""); } } WriteFileTail(); fileStream.Close(); } } }