重写注册逻辑

This commit is contained in:
2026-03-18 15:36:15 +08:00
parent d2a61690de
commit 255c485703
3 changed files with 738 additions and 1283 deletions
+184 -572
View File
@@ -1,572 +1,184 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
namespace ExcelTool namespace ExcelTool
{ {
/// <summary> /// <summary>
/// 文件操作类 /// 文件操作类
/// </summary> /// </summary>
public static class FileManager public static class FileManager
{ {
public static bool CreateDir(string dirPath) public static bool CreateDir(string dirPath)
{ {
if (string.IsNullOrEmpty(dirPath)) if (string.IsNullOrEmpty(dirPath))
return false; return false;
if (Directory.Exists(dirPath)) if (Directory.Exists(dirPath))
{ Directory.Delete(dirPath, true);
Directory.Delete(dirPath, true); Directory.CreateDirectory(dirPath);
} return true;
Directory.CreateDirectory(dirPath); }
return true;
} /// <summary>将数据写入二进制文件(IBinarySerializable 版本)</summary>
public static bool WriteBinaryDataToFile(string filePath, IBinarySerializable data)
/// <summary> {
/// 将数据写入二进制文件 if (string.IsNullOrEmpty(filePath)) return false;
/// </summary> if (File.Exists(filePath)) File.Delete(filePath);
/// <param name="filePath"></param>
/// <param name="data">继承自IBinarySerialize的数据</param> using var fileStream = new FileStream(filePath, FileMode.Create);
public static bool WriteBinaryDataToFile(string filePath, IBinarySerializable data) using var bw = new BinaryWriter(fileStream);
{ data.Serialize(bw);
if (string.IsNullOrEmpty(filePath)) bw.Flush();
return false; return true;
if (File.Exists(filePath)) }
{
File.Delete(filePath); /// <summary>
} /// 将数据写入二进制文件。
using (var fileStream = new FileStream(filePath, FileMode.Create)) /// 类型名(Item1)须与 <see cref="TypeRegistry"/> 中注册的 key 一致(不区分大小写)。
{ /// 额外支持 list&lt;T&gt; 泛型语法。
using (var bw = new BinaryWriter(fileStream)) /// </summary>
{ public static bool WriteBinaryDatasToFile(string filePath, List<Tuple<string, string>> datas)
data.Serialize(bw); {
bw.Flush(); try
bw.Close(); {
} if (string.IsNullOrEmpty(filePath)) return false;
fileStream.Close(); if (File.Exists(filePath)) File.Delete(filePath);
}
return true; using var fileStream = new FileStream(filePath, FileMode.Create);
} using var bw = new BinaryWriter(fileStream);
/// <summary> foreach (var (rawType, value) in datas)
/// 将数据写入二进制文件 {
/// </summary> var type = rawType.ToLower();
/// <param name="filePath"></param>
/// <param name="datas">类型(小写)和value的字符串键值对</param> // ── 优先从注册表查找 ──────────────────────────────
/// <returns></returns> var desc = TypeRegistry.Get(type);
public static bool WriteBinaryDatasToFile(string filePath, List<Tuple<string, string>> datas) if (desc != null)
{ {
try desc.WriteBinary(bw, value);
{ continue;
if (string.IsNullOrEmpty(filePath)) }
return false;
if (File.Exists(filePath)) // ── list<T> 泛型语法(如 list<int>)─────────────
{ if (type.StartsWith("list<") && type.EndsWith(">"))
File.Delete(filePath); {
} WriteGenericList(bw, type, value);
using (var fileStream = new FileStream(filePath, FileMode.Create)) continue;
{ }
using (var bw = new BinaryWriter(fileStream))
{ ConsoleHelper.WriteErrorLine($"写入二进制文件:数据类型 \"{rawType}\" 未注册,请在 TypeRegistry 中添加");
foreach (var data in datas) return false;
{ }
if (data.Item1.Equals("int"))
{ bw.Flush();
if (string.IsNullOrEmpty(data.Item2)) return true;
{ }
bw.Write(Convert.ToInt32(0)); catch (Exception ex)
} {
else ConsoleHelper.WriteErrorLine(ex.ToString());
{ return false;
bw.Write(Convert.ToInt32(data.Item2)); }
} }
}
else if (data.Item1.Equals("uint")) // ──────────────────────────────────────────────────────────────
{ // list<T> 泛型列表写入(T 必须是已在 TypeRegistry 注册的基础类型)
if (string.IsNullOrEmpty(data.Item2)) // ──────────────────────────────────────────────────────────────
{ private static void WriteGenericList(BinaryWriter bw, string fullType, string value)
bw.Write(Convert.ToUInt32(0)); {
} // fullType 形如 "list<int>"
else var innerType = fullType[5..^1]; // 去掉 "list<" 和 ">"
{ var elemDesc = TypeRegistry.Get(innerType);
bw.Write(Convert.ToUInt32(data.Item2)); if (elemDesc == null)
} {
}else if (data.Item1.Equals("short")) ConsoleHelper.WriteErrorLine($"list<T> 的元素类型 \"{innerType}\" 未注册,请在 TypeRegistry 中添加");
{ return;
bw.Write(string.IsNullOrEmpty(data.Item2) ? Convert.ToInt16(0) : Convert.ToInt16(data.Item2)); }
}
else if (data.Item1.Equals("ushort")) if (string.IsNullOrEmpty(value))
{ {
bw.Write(string.IsNullOrEmpty(data.Item2) ? Convert.ToUInt16(0) : Convert.ToUInt16(data.Item2)); bw.Write(0);
} return;
else if (data.Item1.Equals("sbyte")) }
{
if (string.IsNullOrEmpty(data.Item2)) var parts = value.Split(',');
{ bw.Write(parts.Length);
bw.Write(Convert.ToSByte(0)); foreach (var p in parts)
} elemDesc.WriteBinary(bw, p);
else }
{
bw.Write(Convert.ToSByte(data.Item2)); // ──────────────────────────────────────────────────────────────
} // 其余文件工具方法(不涉及类型系统,保持不变)
} // ──────────────────────────────────────────────────────────────
else if (data.Item1.Equals("byte"))
{ public static bool ReadBinaryDataFromBytes(byte[] bytes, ref IBinarySerializable data)
if (string.IsNullOrEmpty(data.Item2)) {
{ if (bytes == null) return false;
bw.Write(Convert.ToByte(0)); using var ms = new MemoryStream(bytes);
} using var br = new BinaryReader(ms);
else data.DeSerialize(br);
{ return true;
bw.Write(Convert.ToByte(data.Item2)); }
}
} public static bool ReadBinaryDataFromFile(string filePath, ref IBinarySerializable data)
else if (data.Item1.Equals("bool")) {
{ if (string.IsNullOrEmpty(filePath)) return false;
if (string.IsNullOrEmpty(data.Item2)) using var fs = new FileStream(filePath, FileMode.Open);
{ using var br = new BinaryReader(fs);
bw.Write(false); data.DeSerialize(br);
} return true;
else }
{
string v = data.Item2.Trim().ToLower(); public static bool WriteBytesToFile(string filePath, byte[] data)
bw.Write(v is "true" or "1"); {
} if (string.IsNullOrEmpty(filePath)) return false;
} if (File.Exists(filePath)) File.Delete(filePath);
else if (data.Item1.Equals("float")) using Stream sw = new FileInfo(filePath).Create();
{ sw.Write(data, 0, data.Length);
if (string.IsNullOrEmpty(data.Item2)) sw.Flush();
{ return true;
bw.Write(Convert.ToSingle(0)); }
}
else public static bool WriteToFile(string filePath, string context) =>
{ WriteToFile(filePath, context, Encoding.Default);
bw.Write(Convert.ToSingle(data.Item2));
} public static bool WriteToFile(string filePath, string context, Encoding encoding)
} {
else if (data.Item1.Equals("double")) if (string.IsNullOrEmpty(filePath)) return false;
{ if (File.Exists(filePath)) File.Delete(filePath);
if (string.IsNullOrEmpty(data.Item2)) using var fs = new FileStream(filePath, FileMode.Create);
{ var data = encoding.GetBytes(context);
bw.Write(Convert.ToDouble(0)); fs.Write(data, 0, data.Length);
} fs.Flush();
else return true;
{ }
bw.Write(Convert.ToDouble(data.Item2));
} public static string ReadAllByLine(string path)
} {
else if (data.Item1.Equals("string")) if (string.IsNullOrEmpty(path) || !File.Exists(path)) return string.Empty;
{ var sb = new StringBuilder();
bw.Write(string.IsNullOrEmpty(data.Item2) ? "" : data.Item2.ToString()); using var sr = new StreamReader(path, Encoding.Default);
} string line;
else if (data.Item1.Equals("long")) while ((line = sr.ReadLine()) != null)
{ sb.AppendLine(line);
if (string.IsNullOrEmpty(data.Item2)) return sb.ToString();
{ }
bw.Write(Convert.ToInt64(0));
} public static byte[] ReadAllBytes(string path) =>
else string.IsNullOrEmpty(path) || !File.Exists(path) ? null : File.ReadAllBytes(path);
{
bw.Write(Convert.ToInt64(data.Item2)); public static void ReplaceContent(string path, string normalStr, string newStr)
} {
} if (string.IsNullOrEmpty(path) || !File.Exists(path)) return;
else if (data.Item1.Equals("vector")) File.WriteAllText(path, File.ReadAllText(path).Replace(normalStr, newStr));
{ }
//[1.2,3.4,5.6]
var str = data.Item2.ToString(); public static void ReplaceContent(string path, string newStr, params string[] normalStrs)
if (string.IsNullOrEmpty(str)) {
{ if (string.IsNullOrEmpty(path) || !File.Exists(path)) return;
bw.Write(Convert.ToInt32(0)); string content = File.ReadAllText(path);
} foreach (var s in normalStrs) content = content.Replace(s, newStr);
else File.WriteAllText(path, content);
{ }
str = str.Replace("]", "").Replace("[", ""); }
var numStrs = str.Split(','); }
int vectorCount = 3;
bw.Write(vectorCount);
for (int i = 0; i < vectorCount; i++)
{
float v = Convert.ToSingle(numStrs[i]);
bw.Write(v);
}
}
}
else if (data.Item1.Equals("vectorlist")) //List<Vector>类型
{
//[[1.2,3.4,5.6],[2.2,3.4,5.6],[3.2,3.4,5.6]]
string str = data.Item2.ToString();
if (string.IsNullOrEmpty(str))
{
bw.Write(Convert.ToInt32(0));
}
else
{
str = str.Replace("]", "").Replace("[", "");
var numStrs = str.Split(',');
bw.Write(Convert.ToInt32(numStrs.Length / 3));
for (int i = 0; i < numStrs.Length; i++)
{
if (i % 3 == 0)
bw.Write(Convert.ToInt32(3));
bw.Write(Convert.ToSingle(numStrs[i]));
}
}
}
else if (data.Item1.Equals("intlist"))
{
string str = data.Item2.ToString();
if (string.IsNullOrEmpty(str))
{
bw.Write(Convert.ToInt32(0));
}
else
{
var numStrs = str.Split(',');
bw.Write(numStrs.Length);
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToInt32(numStrs[i]));
}
}
}
else if (data.Item1.Equals("floatlist"))
{
string str = data.Item2.ToString();
if (string.IsNullOrEmpty(str))
{
bw.Write(Convert.ToInt32(0));
}
else
{
var numStrs = str.Split(',');
bw.Write(numStrs.Length);
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToSingle(numStrs[i]));
}
}
}
else if (data.Item1.Equals("boollist"))
{
string str = data.Item2.ToString();
if (string.IsNullOrEmpty(str))
{
bw.Write(Convert.ToInt32(0));
}
else
{
var numStrs = str.Split(',');
bw.Write(numStrs.Length);
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToBoolean(numStrs[i]));
}
}
}
else if (data.Item1.Equals("stringlist"))
{
string str = data.Item2.ToString();
if (string.IsNullOrEmpty(str))
{
bw.Write(Convert.ToInt32(0));
}
else
{
var numStrs = str.Split(',');
bw.Write(numStrs.Length);
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(numStrs[i]);
}
}
}
else if (data.Item1.Equals("longlist"))
{
string str = data.Item2.ToString();
if (string.IsNullOrEmpty(str))
{
bw.Write(Convert.ToInt32(0));
}
else
{
var numStrs = str.Split(',');
bw.Write(numStrs.Length);
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToInt64(numStrs[i]));
}
}
}
else if (data.Item1.Contains("list<")) //泛型数组类型
{
string str = data.Item2.ToString();
if (string.IsNullOrEmpty(str))
{
bw.Write(Convert.ToInt32(0));
}
else
{
var numStrs = str.Split(',');
bw.Write(numStrs.Length);
var tempS = data.Item1.Substring(5);
var listType = tempS.Substring(0, tempS.Length - 1);
if (listType.Equals("int"))
{
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToInt32(numStrs[i]));
}
}
else if (listType.Equals("uint"))
{
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToUInt32(numStrs[i]));
}
}
else if (listType.Equals("short"))
{
foreach (string t in numStrs)
{
bw.Write(Convert.ToInt16(t));
}
}
else if (listType.Equals("ushort"))
{
foreach (string t in numStrs)
{
bw.Write(Convert.ToUInt16(t));
}
}
else if (listType.Equals("sbyte"))
{
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToSByte(numStrs[i]));
}
}
else if (listType.Equals("byte"))
{
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToByte(numStrs[i]));
}
}
else if (listType.Equals("bool"))
{
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToBoolean(numStrs[i]));
}
}
else if (listType.Equals("float"))
{
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToSingle(numStrs[i]));
}
}
else if (listType.Equals("long"))
{
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToInt64(numStrs[i]));
}
}
else if (listType.Equals("string"))
{
for (int i = 0; i < numStrs.Length; i++)
{
bw.Write(Convert.ToString(numStrs[i]));
}
}
else
{
ConsoleHelper.WriteErrorLine("数组类型List<T>,T不是支持的Int,Float,String这三种类型,需要扩展类型");
}
}
}
else
{
ConsoleHelper.WriteErrorLine($"写入二进制文件,数据类型{data.Item1}没有适配");
return false;
}
}
bw.Flush();
bw.Close();
}
fileStream.Close();
}
return true;
}
catch (Exception ex)
{
ConsoleHelper.WriteErrorLine(ex.ToString());
return false;
}
}
/// <summary>
/// 从内存流中读取二进制
/// </summary>
/// <param name="bytes"></param>
/// <param name="data"></param>
/// <returns></returns>
public static bool ReadBinaryDataFromBytes(byte[] bytes, ref IBinarySerializable data)
{
if (bytes == null)
return false;
using (var memoryStream = new MemoryStream(bytes))
{
using (var br = new BinaryReader(memoryStream))
{
data.DeSerialize(br);
br.Close();
}
memoryStream.Close();
}
return true;
}
/// <summary>
/// 读取二进制文件
/// </summary>
/// <param name="filePath"></param>
/// <param name="data"></param>
/// <returns></returns>
public static bool ReadBinaryDataFromFile(string filePath, ref IBinarySerializable data)
{
if (string.IsNullOrEmpty(filePath))
{
return false;
}
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
using (var br = new BinaryReader(fileStream))
{
data.DeSerialize(br);
br.Close();
}
fileStream.Close();
}
return true;
}
public static bool WriteBytesToFile(string filePath, byte[] data)
{
if (string.IsNullOrEmpty(filePath))
return false;
if (File.Exists(filePath))
{
File.Delete(filePath);
}
var file = new FileInfo(filePath);
using (Stream sw = file.Create())
{
sw.Write(data, 0, data.Length);
sw.Flush();
sw.Close();
}
return true;
}
/// <summary>
/// 将字符串写入文件
/// </summary>
/// <param name="filePath"></param>
/// <param name="context"></param>
/// <returns></returns>
public static bool WriteToFile(string filePath, string context)
{
return WriteToFile(filePath, context, Encoding.Default);
}
public static bool WriteToFile(string filePath, string context, Encoding encoding)
{
if (string.IsNullOrEmpty(filePath))
return false;
if (File.Exists(filePath))
{
File.Delete(filePath);
}
using (FileStream fs = new FileStream(filePath, FileMode.Create))
{
var data = encoding.GetBytes(context);
fs.Write(data, 0, data.Length);
fs.Flush();
fs.Close();
}
return true;
}
/// <summary>
/// 按行读取
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string ReadAllByLine(string path)
{
if (string.IsNullOrEmpty(path) || !File.Exists(path))
{
return string.Empty;
}
StringBuilder sb = new StringBuilder();
using (StreamReader sr = new StreamReader(path, Encoding.Default))
{
string line;
while ((line = sr.ReadLine()) != null)
{
sb.AppendLine(line);
}
sr.Close();
}
return sb.ToString();
}
public static byte[] ReadAllBytes(string path)
{
if (string.IsNullOrEmpty(path) || !File.Exists(path))
{
return null;
}
return File.ReadAllBytes(path);
}
/// <summary>
/// 修改文件内容
/// </summary>
/// <param name="path"></param>
/// <param name="normalStr"></param>
/// <param name="newStr"></param>
public static void ReplaceContent(string path, string normalStr, string newStr)
{
if (string.IsNullOrEmpty(path) || !File.Exists(path))
{
return;
}
string strContent = File.ReadAllText(path);
strContent = strContent.Replace(normalStr, newStr);
File.WriteAllText(path, strContent);
}
/// <summary>
/// 批量修改文件内容
/// </summary>
/// <param name="path"></param>
/// <param name="newStr"></param>
/// <param name="normalStrs"></param>
public static void ReplaceContent(string path, string newStr, params string[] normalStrs)
{
if (string.IsNullOrEmpty(path) || !File.Exists(path))
{
return;
}
string strContent = File.ReadAllText(path);
for (int i = 0; i < normalStrs.Length; i++)
{
strContent = strContent.Replace(normalStrs[i], newStr);
}
File.WriteAllText(path, strContent);
}
}
}
+276 -711
View File
@@ -1,711 +1,276 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
namespace ExcelTool.Parser namespace ExcelTool.Parser
{ {
public static class GenModels public static class GenModels
{ {
/// <summary> // ── 枚举类型映射(key: 小写类型名,value: C# 枚举类型名)──────────────
/// 生成对应的C#Model类 // 新增枚举类型只改这里
/// </summary> private static readonly Dictionary<string, string> EnumMap = new()
/// <param name="fileName">传入的文件名</param> {
/// <param name="outputDir">输出cs文件的路径</param> { "killmode", "KillMode" },
/// <param name="nameSpace">cs文件要使用的命名空间</param> { "mixingtype", "MixingType" },
/// <returns></returns> { "containertype", "ContainerType" },
public static bool GenCSharpModel(string fileName, string outputDir, string nameSpace = "") { "blendcrossfadetype","BlendCrossFadeType" },
{ };
if (string.IsNullOrEmpty(fileName))
{ /// <summary>
"GenCSharpModel 参数传递有误".WriteErrorLine(); /// 生成对应的 C# Model 类
return false; /// </summary>
} public static bool GenCSharpModel(string fileName, string outputDir, string nameSpace = "")
try {
{ if (string.IsNullOrEmpty(fileName))
// 枚举类型映射 {
Dictionary<string, string> enumMap = new() "GenCSharpModel 参数传递有误".WriteErrorLine();
{ return false;
{ "killmode", "KillMode" }, }
{ "mixingtype", "MixingType" },
{ "containertype", "ContainerType" }, try
{ "blendcrossfadetype", "BlendCrossFadeType" } {
}; FileInfo fileInfo = new(fileName);
FileInfo fileInfo = new(fileName); if (string.IsNullOrEmpty(outputDir))
if (string.IsNullOrEmpty(outputDir)) outputDir = fileInfo.DirectoryName;
{
outputDir = fileInfo.DirectoryName; for (int sheetNum = 0; ; sheetNum++)
} {
for (int sheetNum = 0; ; sheetNum++) var headers = ExcelHelper.ExcelHeaders(fileName, out string sheetName, out int sheetCount, sheetNum);
{ if (headers == null || headers.Count == 0 || sheetName.StartsWith('#') || sheetNum > sheetCount)
var headers = ExcelHelper.ExcelHeaders(fileName, out string sheetName, out int sheetCount, sheetNum); break;
if (headers == null || headers.Count == 0 || sheetName.StartsWith("#") || sheetNum > sheetCount)
break; var sb = new StringBuilder();
StringBuilder sb = new(); sb.Append($"/*\n * auto generated by tools(注意:千万不要手动修改本文件)\n * {sheetName}\n */\n");
sb.Append($"/*\n * auto generated by tools(注意:千万不要手动修改本文件)\n * {sheetName}\n */\n"); sb.Append("using System;\nusing System.IO;\nusing System.Collections.Generic;\nusing System.Text;\nusing WKMobile.Generated;\n\n");
sb.Append("using System;\nusing System.IO;\nusing System.Collections.Generic;\nusing System.Text;\nusing WKMobile.Generated;\n\n");
if (!string.IsNullOrEmpty(nameSpace))
sb.Append($"namespace {nameSpace}\n{{\n");
if (!string.IsNullOrEmpty(nameSpace))
{ // ── 数据行类 ─────────────────────────────────────────────────
sb.Append($"namespace {nameSpace}\n{{\n"); sb.Append("[Serializable]\n");
} sb.Append($"public partial class {sheetName} : IBinarySerializable\n");
sb.Append("{\n");
sb.Append("[Serializable]\n");
sb.Append($"public partial class {sheetName} : IBinarySerializable\n"); foreach (var header in headers)
sb.Append("{\n"); AppendProperty(sb, header);
for (int i = 0; i < headers.Count; i++)
{ AppendDeserializeMethod(sb, headers, sheetName);
sb.Append($"\t/// <summary>\n"); AppendSerializeMethod(sb, headers, sheetName);
var descLines = headers[i].FieldDesc?.Replace("\r", "").Split('\n');
if (descLines != null) sb.Append("}\n\n");
{
foreach (var line in descLines) // ── Config 容器类 ─────────────────────────────────────────────
{ AppendConfigClass(sb, sheetName);
sb.Append($"\t/// {line}\n");
} if (!string.IsNullOrEmpty(nameSpace))
} sb.Append("}\n");
sb.Append($"\t/// </summary>\n");
var type = headers[i].FieldType.ToLower(); FileManager.WriteToFile(Path.Combine(outputDir, $"{sheetName}.cs"), sb.ToString());
var origType = headers[i].FieldType; }
var fieldName = headers[i].FieldName;
if (enumMap.ContainsKey(type)) return true;
{ }
sb.Append($"\tpublic {enumMap[type]} {fieldName} {{ get; set; }}\n\n"); catch (Exception ex)
} {
else if (type.Equals("vector")) ex.ToString().WriteErrorLine();
{ return false;
sb.Append(string.Format("\tpublic List<float> {0}", headers[i].FieldName)); }
sb.Append(" { get; set; }\n\n"); }
}
else if (type.Equals("vectorlist")) // ──────────────────────────────────────────────────────────────────────────
{ // 属性声明
sb.Append(string.Format("\tpublic List<List<float>> {0}", headers[i].FieldName)); // ──────────────────────────────────────────────────────────────────────────
sb.Append(" { get; set; }\n\n");
} private static void AppendProperty(StringBuilder sb, TableExcelHeader header)
else if (type.Equals("intlist")) {
{ // XML 注释
sb.Append(string.Format("\tpublic List<int> {0}", headers[i].FieldName)); sb.Append("\t/// <summary>\n");
sb.Append(" { get; set; }\n\n"); var descLines = header.FieldDesc?.Replace("\r", "").Split('\n');
} if (descLines != null)
else if (type.Equals("boollist")) foreach (var line in descLines)
{ sb.Append($"\t/// {line}\n");
sb.Append(string.Format("\tpublic List<bool> {0}", headers[i].FieldName)); sb.Append("\t/// </summary>\n");
sb.Append(" { get; set; }\n\n");
} var csType = ResolveCSharpType(header.FieldType);
else if (type.Equals("floatlist")) sb.Append($"\tpublic {csType} {header.FieldName} {{ get; set; }}\n\n");
{ }
sb.Append(string.Format("\tpublic List<float> {0}", headers[i].FieldName));
sb.Append(" { get; set; }\n\n"); // ──────────────────────────────────────────────────────────────────────────
} // DeSerialize 方法
else if (type.Equals("stringlist")) // ──────────────────────────────────────────────────────────────────────────
{
sb.Append(string.Format("\tpublic List<string> {0}", headers[i].FieldName)); private static void AppendDeserializeMethod(StringBuilder sb, List<TableExcelHeader> headers, string sheetName)
sb.Append(" { get; set; }\n\n"); {
} sb.Append("\n\tpublic void DeSerialize(BinaryReader reader)\n\t{\n");
else if (type.Equals("longlist"))
{ foreach (var header in headers)
sb.Append(string.Format("\tpublic List<long> {0}", headers[i].FieldName)); {
sb.Append(" { get; set; }\n\n"); var type = header.FieldType.ToLower();
} var name = header.FieldName;
else if (type.Equals("uintlist"))
{ // 枚举
sb.Append(string.Format("\tpublic List<uint> {0}", headers[i].FieldName)); if (EnumMap.TryGetValue(type, out var enumCsType))
sb.Append(" { get; set; }\n\n"); {
} sb.Append($"\t\t{name} = ({enumCsType})reader.ReadByte();\n");
else if (type.Equals("ushortlist")) continue;
{ }
sb.Append(string.Format("\tpublic List<ushort> {0}", headers[i].FieldName));
sb.Append(" { get; set; }\n\n"); // 注册表中的具名类型
} var desc = TypeRegistry.Get(type);
else if (type.Equals("sbytelist")) if (desc != null)
{ {
sb.Append(string.Format("\tpublic List<sbyte> {0}", headers[i].FieldName)); sb.Append(desc.GenDeserialize(name));
sb.Append(" { get; set; }\n\n"); continue;
} }
else if (type.Equals("bytelist"))
{ // list<T> 泛型语法
sb.Append(string.Format("\tpublic List<byte> {0}", headers[i].FieldName)); if (TryParseGenericList(type, out var elemType))
sb.Append(" { get; set; }\n\n"); {
} var elemDesc = TypeRegistry.Get(elemType);
else if (type.Contains("list<")) if (elemDesc == null)
{ {
var tempS = type.Substring(5); $"list<T> 的元素类型 \"{elemType}\" 未注册 ({sheetName})".WriteErrorLine();
var newType = tempS.Substring(0, tempS.Length - 1); continue;
if (newType.Equals("int")) }
{ // 读取表达式复用注册表中的 GenDeserialize 只取 ReadXxx() 部分比较麻烦,
sb.Append(string.Format("\tpublic List<int> {0}", headers[i].FieldName)); // 这里直接用公共辅助方法生成片段
sb.Append(" { get; set; }\n\n"); sb.Append(TypeRegistry.GenListDeserialize(name, elemDesc.CSharpType, GetReadExpr(elemDesc)));
} continue;
else if (newType.Equals("bool")) }
{
sb.Append(string.Format("\tpublic List<bool> {0}", headers[i].FieldName)); $"类型 \"{type}\" 未注册,{sheetName} 处理异常".WriteErrorLine();
sb.Append(" { get; set; }\n\n"); }
}
else if (newType.Equals("float")) sb.Append("\t}\n");
{ }
sb.Append(string.Format("\tpublic List<float> {0}", headers[i].FieldName));
sb.Append(" { get; set; }\n\n"); // ──────────────────────────────────────────────────────────────────────────
} // Serialize 方法
else if (newType.Equals("long")) // ──────────────────────────────────────────────────────────────────────────
{
sb.Append(string.Format("\tpublic List<long> {0}", headers[i].FieldName)); private static void AppendSerializeMethod(StringBuilder sb, List<TableExcelHeader> headers, string sheetName)
sb.Append(" { get; set; }\n\n"); {
} sb.Append("\n\tpublic void Serialize(BinaryWriter writer)\n\t{\n");
else if (newType.Equals("string"))
{ foreach (var header in headers)
sb.Append(string.Format("\tpublic List<string> {0}", headers[i].FieldName)); {
sb.Append(" { get; set; }\n\n"); var type = header.FieldType.ToLower();
} var name = header.FieldName;
else
{ // 枚举
ConsoleHelper.WriteErrorLine("数组类型List<T>T类型不支持"); if (EnumMap.ContainsKey(type))
} {
} sb.Append($"\t\twriter.Write((byte){name});\n");
else continue;
{ }
sb.Append(string.Format("\tpublic {0} {1}", headers[i].FieldType.ToLower(), headers[i].FieldName));
sb.Append(" { get; set; }\n\n"); // 注册表
} var desc = TypeRegistry.Get(type);
} if (desc != null)
sb.Append("\n\tpublic void DeSerialize(BinaryReader reader)\n"); {
sb.Append("\t{\n"); sb.Append(desc.GenSerialize(name));
foreach (var header in headers) continue;
{ }
var type = header.FieldType.ToLower();
var name = header.FieldName; // list<T> 泛型语法
if (enumMap.ContainsKey(type)) if (TryParseGenericList(type, out _))
{ {
sb.Append($"\t\t{name} = ({enumMap[type]})reader.ReadByte();\n"); sb.Append(TypeRegistry.GenListSerialize(name));
} continue;
else if (type.Equals("int")) }
{
sb.Append($"\t\t{name} = reader.ReadInt32();\n"); $"类型 \"{type}\" 未注册,{sheetName} 处理异常".WriteErrorLine();
} }
else if (type.Equals("uint"))
{ sb.Append("\t}\n");
sb.Append($"\t\t{name} = reader.ReadUInt32();\n"); }
}
else if (type.Equals("short")) // ──────────────────────────────────────────────────────────────────────────
{ // Config 容器类(不涉及类型系统,逻辑不变,仅格式整理)
sb.Append($"\t\t{name} = reader.ReadInt16();\n"); // ──────────────────────────────────────────────────────────────────────────
}
else if (type.Equals("ushort")) private static void AppendConfigClass(StringBuilder sb, string name)
{ {
sb.Append($"\t\t{name} = reader.ReadUInt16();\n"); var camel = name.ToCamelCase();
} sb.Append("[Serializable]\n");
else if (type.Equals("sbyte")) sb.Append($"public partial class {name}Config : IBinarySerializable\n{{\n");
{ sb.Append($"\tDictionary<uint,{name}> m_{camel}Infos = new();\n");
sb.Append($"\t\t{name} = reader.ReadSByte();\n"); sb.Append($"\tList<{name}> m_{camel}InfoList;\n\n");
}
else if (type.Equals("byte")) sb.Append($"\tpublic List<{name}> {name}List()\n\t{{\n");
{ sb.Append($"\t\tthis.m_{camel}InfoList ??= new List<{name}>(m_{camel}Infos.Values);\n");
sb.Append($"\t\t{name} = reader.ReadByte();\n"); sb.Append($"\t\treturn this.m_{camel}InfoList;\n\t}}\n\n");
}
else if (type.Equals("bool")) sb.Append($"\tpublic void DeSerialize(BinaryReader reader)\n\t{{\n");
{ sb.Append($"\t\tint count = reader.ReadInt32();\n");
sb.Append($"\t\t{name} = reader.ReadBoolean();\n"); sb.Append($"\t\tfor (int i = 0; i < count; i++)\n\t\t{{\n");
} sb.Append($"\t\t\t{name} tempData = new();\n");
else if (type.Equals("float")) sb.Append($"\t\t\ttempData.DeSerialize(reader);\n");
{ sb.Append($"\t\t\tthis.m_{camel}Infos.Add(tempData.Id, tempData);\n");
sb.Append($"\t\t{name} = reader.ReadSingle();\n"); sb.Append("\t\t}\n\t}\n\n");
}
else if (type.Equals("string")) sb.Append($"\tpublic void Serialize(BinaryWriter writer)\n\t{{\n");
{ sb.Append($"\t\twriter.Write(this.m_{camel}Infos.Count);\n");
sb.Append($"\t\t{name} = reader.ReadString();\n"); sb.Append($"\t\tforeach ({name} {camel} in this.m_{camel}Infos.Values)\n\t\t{{\n");
} sb.Append($"\t\t\t{camel}.Serialize(writer);\n");
else if (type.Equals("vector")) sb.Append("\t\t}\n\t}\n\n");
{
sb.Append($"\t\tvar {name.ToCamelCase()}Count = reader.ReadInt32();\n"); sb.Append($"\tpublic {name} QueryById(uint id)\n\t{{\n");
sb.Append($"\t\tif ({name.ToCamelCase()}Count > 0)\n"); sb.Append($"\t\treturn this.m_{camel}Infos.GetValueOrDefault(id);\n");
sb.Append("\t\t{\n"); sb.Append("\t}\n}\n");
sb.Append($"\t\t\t{name} = new List<float>();\n"); }
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n"); // ──────────────────────────────────────────────────────────────────────────
sb.Append($"\t\t\t\t{name}.Add(reader.ReadSingle());\n"); // 工具方法
sb.Append("\t\t\t}\n"); // ──────────────────────────────────────────────────────────────────────────
sb.Append("\t\t}\n");
sb.Append("\t\telse\n"); /// <summary>把字段类型名解析为 C# 属性类型字符串</summary>
sb.Append("\t\t{\n"); private static string ResolveCSharpType(string fieldType)
sb.Append($"\t\t\t{name} = null;\n"); {
sb.Append("\t\t}\n"); var lower = fieldType.ToLower();
}
else if (type.Equals("vectorlist")) if (EnumMap.TryGetValue(lower, out var enumType))
{ return enumType;
sb.Append($"\t\tvar {name.ToCamelCase()}Count = reader.ReadInt32();\n");
sb.Append($"\t\tif ({name.ToCamelCase()}Count > 0)\n"); var desc = TypeRegistry.Get(lower);
sb.Append("\t\t{\n"); if (desc != null)
sb.Append($"\t\t\t{name} = new List<List<float>>();\n"); return desc.CSharpType;
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n"); // list<T> 泛型
sb.Append($"\t\t\t\tvar tempList = new List<float>();\n"); if (TryParseGenericList(lower, out var elemType))
sb.Append($"\t\t\t\tvar tempListCount = reader.ReadInt32();\n"); {
sb.Append($"\t\t\t\tfor (int j = 0; j < tempListCount; j++)\n"); var elemDesc = TypeRegistry.Get(elemType);
sb.Append("\t\t\t\t{\n"); return elemDesc != null ? $"List<{elemDesc.CSharpType}>" : $"List<{elemType}>";
sb.Append($"\t\t\t\t\ttempList.Add(reader.ReadSingle());\n"); }
sb.Append("\t\t\t\t}\n");
sb.Append($"\t\t\t\t{name}.Add(tempList);\n"); // 兜底:直接用原始类型名(可能是用户自定义类型)
sb.Append("\t\t\t}\n"); return fieldType.ToLower();
sb.Append("\t\t}\n"); }
sb.Append("\t\telse\n");
sb.Append("\t\t{\n"); /// <summary>尝试解析 list&lt;T&gt; 语法,成功返回元素类型名</summary>
sb.Append($"\t\t\t{name} = null;\n"); private static bool TryParseGenericList(string type, out string elemType)
sb.Append("\t\t}\n"); {
} if (type.StartsWith("list<") && type.EndsWith(">"))
else if (type.Equals("intlist")) {
{ elemType = type[5..^1];
sb.Append($"\t\tvar {name.ToCamelCase()}Count = reader.ReadInt32();\n"); return true;
sb.Append($"\t\tif ({name.ToCamelCase()}Count > 0)\n"); }
sb.Append("\t\t{\n"); elemType = null;
sb.Append($"\t\t\t{name} = new List<int>();\n"); return false;
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n"); }
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadInt32());\n"); /// <summary>从 TypeDescriptor 反推 reader.ReadXxx() 表达式(用于 list&lt;T&gt; 代码生成)</summary>
sb.Append("\t\t\t}\n"); private static string GetReadExpr(TypeDescriptor desc)
sb.Append("\t\t}\n"); {
sb.Append("\t\telse\n"); // GenDeserialize 生成的行形如 "\t\tname = reader.ReadXxx();\n"
sb.Append("\t\t{\n"); // 这里简单地从注册表拿一个占位 name 然后截取表达式部分
sb.Append($"\t\t\t{name} = null;\n"); const string placeholder = "__x__";
sb.Append("\t\t}\n"); var line = desc.GenDeserialize(placeholder).Trim(); // "x = reader.ReadXxx();"
}else if (type.Equals("uintlist")) var eqIdx = line.IndexOf('=');
{ return eqIdx >= 0
sb.Append($"\t\tvar {name.ToCamelCase()}Count = reader.ReadInt32();\n"); ? line[(eqIdx + 1)..].TrimEnd(';').Trim() // "reader.ReadXxx()"
sb.Append($"\t\tif ({name.ToCamelCase()}Count > 0)\n"); : $"/* unknown read for {desc.TypeName} */";
sb.Append("\t\t{\n"); }
sb.Append($"\t\t\t{name} = new List<uint>();\n"); }
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n"); }
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadUInt32());\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{name} = null;\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("boollist"))
{
sb.Append($"\t\tvar {name.ToCamelCase()}Count = reader.ReadInt32();\n");
sb.Append($"\t\tif ({name.ToCamelCase()}Count > 0)\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{name} = new List<bool>();\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadBoolean());\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{name} = null;\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("floatlist"))
{
sb.Append($"\t\tvar {name.ToCamelCase()}Count = reader.ReadInt32();\n");
sb.Append($"\t\tif ({name.ToCamelCase()}Count > 0)\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{name} = new List<float>();\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadSingle());\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{name} = null;\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("stringlist"))
{
sb.Append($"\t\tvar {name.ToCamelCase()}Count = reader.ReadInt32();\n");
sb.Append($"\t\tif ({name.ToCamelCase()}Count > 0)\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{name} = new List<string>();\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadString());\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{name} = null;\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("longlist"))
{
sb.Append($"\t\tvar {name.ToCamelCase()}Count = reader.ReadInt32();\n");
sb.Append($"\t\tif ({name.ToCamelCase()}Count > 0)\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{name} = new List<long>();\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadInt64());\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{name} = null;\n");
sb.Append("\t\t}\n");
}
else if (type.Contains("list<"))
{
var tempS = type.Substring(5);
var listTType = tempS.Substring(0, tempS.Length - 1);
sb.Append($"\t\tvar {name.ToCamelCase()}Count = reader.ReadInt32();\n");
sb.Append($"\t\tif ({name.ToCamelCase()}Count > 0)\n");
sb.Append("\t\t{\n");
if (listTType.Equals("int"))
{
sb.Append($"\t\t\t{name} = new List<int>();\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadInt32());\n");
}
else if (listTType.Equals("bool"))
{
sb.Append($"\t\t\t{name} = new List<bool>();\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadBoolean());\n");
}
else if (listTType.Equals("float"))
{
sb.Append($"\t\t\t{name} = new List<float>();\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadSingle());\n");
}
else if (listTType.Equals("long"))
{
sb.Append($"\t\t\t{name} = new List<long>();\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadInt64());\n");
}
else if (listTType.Equals("string"))
{
sb.Append($"\t\t\t{name} = new List<string>();\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name.ToCamelCase()}Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\t{name}.Add(reader.ReadString());\n");
}
else
{
"数组泛型T不是指定类型".WriteErrorLine();
}
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{name} = null;\n");
sb.Append("\t\t}\n");
}
else
{
$"类型:{type}没有解析 {fileName}处理异常".WriteErrorLine();
return false;
}
}
sb.Append("\t}\n\n");
sb.Append("\tpublic void Serialize(BinaryWriter writer)\n");
sb.Append("\t{\n");
foreach (var header in headers)
{
var type = header.FieldType.ToLower();
var name = header.FieldName;
if (enumMap.ContainsKey(type))
{
sb.Append($"\t\twriter.Write((byte){name});\n");
}
else if (type.Equals("int") ||
type.Equals("bool") ||
type.Equals("float") ||
type.Equals("string") ||
type.Equals("uint") ||
type.Equals("ushort") ||
type.Equals("short") ||
type.Equals("sbyte") ||
type.Equals("byte"))
{
sb.Append($"\t\twriter.Write({name});\n");
}
else if (type.Equals("vector"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("vectorlist"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i].Count);\n");
sb.Append($"\t\t\t\tfor (int j = 0; j < {name}[i].Count; j++)\n");
sb.Append("\t\t\t\t{\n");
sb.Append($"\t\t\t\t\twriter.Write({name}[i][j]);\n");
sb.Append("\t\t\t\t}\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("intlist"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("boollist"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("floatlist"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("longlist"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("stringlist"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("uintlist"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("ushortlist"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("sbytelist"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Equals("bytelist"))
{
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
}
else if (type.Contains("list<"))
{
var tempS = type.Substring(5);
var listTType = tempS.Substring(0, tempS.Length - 1);
sb.Append($"\t\tif ({name} == null || {name}.Count == 0)\n");
sb.Append("\t\t{\n");
sb.Append("\t\t\twriter.Write(0);\n");
sb.Append("\t\t}\n");
sb.Append("\t\telse\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\twriter.Write({name}.Count);\n");
sb.Append($"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n");
sb.Append("\t\t\t{\n");
sb.Append($"\t\t\t\twriter.Write({name}[i]);\n");
sb.Append("\t\t\t}\n");
sb.Append("\t\t}\n");
if (listTType.Equals("int"))
{
}
else if (listTType.Equals("bool"))
{
}
else if (listTType.Equals("float"))
{
}
else if (listTType.Equals("long"))
{
}
else if (listTType.Equals("string"))
{
}
else
{
ConsoleHelper.WriteErrorLine("数组泛型T不是指定类型");
}
}
else
{
ConsoleHelper.WriteErrorLine($"类型:{type}没有解析 {fileName}处理异常");
return false;
}
}
sb.Append("\t}\n");
sb.Append("}\n");
sb.Append("\n");
sb.Append("[Serializable]\n");
sb.Append($"public partial class {sheetName}Config : IBinarySerializable\n");
sb.Append("{\n");
// sb.Append($"\tpublic List<{excelName}> {excelName}Infos = new List<{excelName}>();\n");
sb.Append($"\tDictionary<uint,{sheetName}> m_{sheetName.ToCamelCase()}Infos = new();\n");
sb.Append($"\tList<{sheetName}> m_{sheetName.ToCamelCase()}InfoList;\n");
sb.Append("\n");
sb.Append($"\tpublic List<{sheetName}> {sheetName}List()\n");
sb.Append("\t{\n");
sb.Append($"\t\tthis.m_{sheetName.ToCamelCase()}InfoList ??= new List<{sheetName}>(m_{sheetName.ToCamelCase()}Infos.Values);\n");
sb.Append($"\t\treturn this.m_{sheetName.ToCamelCase()}InfoList;\n");
sb.Append("\t}\n");
sb.Append("\n");
sb.Append($"\tpublic void DeSerialize(BinaryReader reader)\n");
sb.Append("\t{\n");
sb.Append($"\t\tint count = reader.ReadInt32();\n");
sb.Append($"\t\tfor (int i = 0;i < count; i++)\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{sheetName} tempData = new();\n");
sb.Append($"\t\t\ttempData.DeSerialize(reader);\n");
// sb.Append($"\t\t\t{excelName}Infos.Add(tempData);\n");
sb.Append($"\t\t\tthis.m_{sheetName.ToCamelCase()}Infos.Add(tempData.Id, tempData);\n");
sb.Append("\t\t}\n");
sb.Append("\t}\n");
sb.Append("\n");
sb.Append("\tpublic void Serialize(BinaryWriter writer)\n");
sb.Append("\t{\n");
sb.Append($"\t\twriter.Write(this.m_{sheetName.ToCamelCase()}Infos.Count);\n");
sb.Append($"\t\tforeach ({sheetName} {sheetName.ToCamelCase()} in this.m_{sheetName.ToCamelCase()}Infos.Values)\n");
sb.Append("\t\t{\n");
sb.Append($"\t\t\t{sheetName.ToCamelCase()}.Serialize(writer);\n");
sb.Append("\t\t}\n");
sb.Append("\t}\n\n");
sb.Append($"\tpublic {sheetName} QueryById(uint id)\n");
sb.Append("\t{\n");
// sb.Append($"\t\tvar datas = from d in {excelName}Infos\n");
// sb.Append($"\t\t\t\t\twhere d.Id == id\n");
// sb.Append($"\t\t\t\t\tselect d;\n");
// sb.Append("\t\treturn datas.First();\n");
sb.Append($"\t\treturn this.m_{sheetName.ToCamelCase()}Infos.GetValueOrDefault(id);\n");
sb.Append("\t}\n");
sb.Append("}\n");
if (!string.IsNullOrEmpty(nameSpace))
{
sb.Append("}\n"); // namespace 结束
}
FileManager.WriteToFile(Path.Combine(outputDir, $"{sheetName}.cs"), sb.ToString());
}
return true;
}
catch (Exception ex)
{
ex.ToString().WriteErrorLine();
return false;
}
}
}
}
+278
View File
@@ -0,0 +1,278 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace ExcelTool
{
/// <summary>
/// 类型描述符:集中管理单个类型的「二进制写入」和「C# 代码生成」逻辑。
/// 新增类型时只需在 TypeRegistry.Register() 里追加一条注册即可。
/// </summary>
public class TypeDescriptor
{
/// <summary>小写类型名,作为注册 key</summary>
public string TypeName { get; init; }
/// <summary>对应的 C# 属性类型字符串,例如 "int"、"List&lt;float&gt;"</summary>
public string CSharpType { get; init; }
/// <summary>将字符串值写入 BinaryWriter 的逻辑</summary>
public Action<BinaryWriter, string> WriteBinary { get; init; }
/// <summary>
/// 生成 DeSerialize 方法体片段(变量名 → 代码行)
/// 返回的字符串已含换行,调用方直接 sb.Append 即可
/// </summary>
public Func<string, string> GenDeserialize { get; init; }
/// <summary>
/// 生成 Serialize 方法体片段(变量名 → 代码行)
/// </summary>
public Func<string, string> GenSerialize { get; init; }
}
/// <summary>
/// 类型注册表。所有支持的字段类型统一在这里注册,一处修改全局生效。
/// </summary>
public static class TypeRegistry
{
private static readonly Dictionary<string, TypeDescriptor> s_map = new();
static TypeRegistry()
{
RegisterAll();
}
// ──────────────────────────────────────────────
// 对外查询
// ──────────────────────────────────────────────
/// <summary>查找类型描述符,找不到返回 null</summary>
public static TypeDescriptor Get(string typeName) =>
s_map.TryGetValue(typeName.ToLower(), out var desc) ? desc : null;
/// <summary>是否包含该类型</summary>
public static bool Contains(string typeName) => s_map.ContainsKey(typeName.ToLower());
// ──────────────────────────────────────────────
// 注册入口:新增类型只需在此追加 Register(...)
// ──────────────────────────────────────────────
private static void RegisterAll()
{
// ---------- 基础值类型 ----------
RegisterPrimitive("int", "int", "reader.ReadInt32()", (bw, v) => bw.Write(string.IsNullOrEmpty(v) ? 0 : Convert.ToInt32(v))) ;
RegisterPrimitive("uint", "uint", "reader.ReadUInt32()", (bw, v) => bw.Write(string.IsNullOrEmpty(v) ? 0u : Convert.ToUInt32(v))) ;
RegisterPrimitive("short", "short", "reader.ReadInt16()", (bw, v) => bw.Write(string.IsNullOrEmpty(v) ? (short)0 : Convert.ToInt16(v))) ;
RegisterPrimitive("ushort", "ushort", "reader.ReadUInt16()", (bw, v) => bw.Write(string.IsNullOrEmpty(v) ? (ushort)0 : Convert.ToUInt16(v))) ;
RegisterPrimitive("sbyte", "sbyte", "reader.ReadSByte()", (bw, v) => bw.Write(string.IsNullOrEmpty(v) ? (sbyte)0 : Convert.ToSByte(v))) ;
RegisterPrimitive("byte", "byte", "reader.ReadByte()", (bw, v) => bw.Write(string.IsNullOrEmpty(v) ? (byte)0 : Convert.ToByte(v))) ;
RegisterPrimitive("float", "float", "reader.ReadSingle()", (bw, v) => bw.Write(string.IsNullOrEmpty(v) ? 0f : Convert.ToSingle(v))) ;
RegisterPrimitive("double", "double", "reader.ReadDouble()", (bw, v) => bw.Write(string.IsNullOrEmpty(v) ? 0d : Convert.ToDouble(v))) ;
RegisterPrimitive("long", "long", "reader.ReadInt64()", (bw, v) => bw.Write(string.IsNullOrEmpty(v) ? 0L : Convert.ToInt64(v))) ;
RegisterPrimitive("string", "string", "reader.ReadString()", (bw, v) => bw.Write(v ?? "")) ;
// bool 单独处理(解析逻辑稍特殊)
Register(new TypeDescriptor
{
TypeName = "bool",
CSharpType = "bool",
WriteBinary = (bw, v) =>
{
if (string.IsNullOrEmpty(v)) { bw.Write(false); return; }
var s = v.Trim().ToLower();
bw.Write(s is "true" or "1");
},
GenDeserialize = name => $"\t\t{name} = reader.ReadBoolean();\n",
GenSerialize = name => $"\t\twriter.Write({name});\n",
});
// ---------- 集合类型 ----------
// vector → List<float>(固定 3 分量,写入时先写分量数)
Register(new TypeDescriptor
{
TypeName = "vector",
CSharpType = "List<float>",
WriteBinary = (bw, v) =>
{
if (string.IsNullOrEmpty(v)) { bw.Write(0); return; }
var parts = v.Replace("]", "").Replace("[", "").Split(',');
int count = 3;
bw.Write(count);
for (int i = 0; i < count; i++)
bw.Write(Convert.ToSingle(parts[i]));
},
GenDeserialize = name => GenListDeserialize(name, "float", "reader.ReadSingle()"),
GenSerialize = name => GenListSerialize(name),
});
// vectorlist → List<List<float>>
Register(new TypeDescriptor
{
TypeName = "vectorlist",
CSharpType = "List<List<float>>",
WriteBinary = (bw, v) =>
{
if (string.IsNullOrEmpty(v)) { bw.Write(0); return; }
var parts = v.Replace("]", "").Replace("[", "").Split(',');
bw.Write(parts.Length / 3);
for (int i = 0; i < parts.Length; i++)
{
if (i % 3 == 0) bw.Write(3);
bw.Write(Convert.ToSingle(parts[i]));
}
},
GenDeserialize = name => GenVectorListDeserialize(name),
GenSerialize = name => GenVectorListSerialize(name),
});
// 简写集合类型(xxxlist
RegisterList("intlist", "int", "reader.ReadInt32()", (bw, s) => bw.Write(Convert.ToInt32(s)));
RegisterList("uintlist", "uint", "reader.ReadUInt32()", (bw, s) => bw.Write(Convert.ToUInt32(s)));
RegisterList("shortlist", "short", "reader.ReadInt16()", (bw, s) => bw.Write(Convert.ToInt16(s)));
RegisterList("ushortlist", "ushort", "reader.ReadUInt16()", (bw, s) => bw.Write(Convert.ToUInt16(s)));
RegisterList("sbytelist", "sbyte", "reader.ReadSByte()", (bw, s) => bw.Write(Convert.ToSByte(s)));
RegisterList("bytelist", "byte", "reader.ReadByte()", (bw, s) => bw.Write(Convert.ToByte(s)));
RegisterList("boollist", "bool", "reader.ReadBoolean()",(bw, s) => bw.Write(Convert.ToBoolean(s)));
RegisterList("floatlist", "float", "reader.ReadSingle()", (bw, s) => bw.Write(Convert.ToSingle(s)));
RegisterList("doublelist", "double", "reader.ReadDouble()", (bw, s) => bw.Write(Convert.ToDouble(s)));
RegisterList("longlist", "long", "reader.ReadInt64()", (bw, s) => bw.Write(Convert.ToInt64(s)));
RegisterList("stringlist", "string", "reader.ReadString()", (bw, s) => bw.Write(s));
}
// ──────────────────────────────────────────────
// 注册辅助
// ──────────────────────────────────────────────
public static void Register(TypeDescriptor desc) =>
s_map[desc.TypeName.ToLower()] = desc;
/// <summary>注册基础值类型的快捷方法</summary>
private static void RegisterPrimitive(
string typeName,
string csType,
string readExpr,
Action<BinaryWriter, string> writeBinary)
{
Register(new TypeDescriptor
{
TypeName = typeName,
CSharpType = csType,
WriteBinary = writeBinary,
GenDeserialize = name => $"\t\t{name} = {readExpr};\n",
GenSerialize = name => $"\t\twriter.Write({name});\n",
});
}
/// <summary>注册 xxxlist 简写集合类型的快捷方法</summary>
private static void RegisterList(
string typeName,
string elemCsType,
string readElemExpr,
Action<BinaryWriter, string> writeElem)
{
Register(new TypeDescriptor
{
TypeName = typeName,
CSharpType = $"List<{elemCsType}>",
WriteBinary = (bw, v) =>
{
if (string.IsNullOrEmpty(v)) { bw.Write(0); return; }
var parts = v.Split(',');
bw.Write(parts.Length);
foreach (var p in parts) writeElem(bw, p);
},
GenDeserialize = name => GenListDeserialize(name, elemCsType, readElemExpr),
GenSerialize = name => GenListSerialize(name),
});
}
// ──────────────────────────────────────────────
// 公共代码生成片段(供 GenModels 中 list<T> 泛型语法共用)
// ──────────────────────────────────────────────
/// <summary>生成 List&lt;T&gt; 的 DeSerialize 片段</summary>
public static string GenListDeserialize(string name, string elemCsType, string readElemExpr)
{
var camel = StringExtensions.ToCamelCase(name);
return
$"\t\tvar {camel}Count = reader.ReadInt32();\n" +
$"\t\tif ({camel}Count > 0)\n" +
"\t\t{\n" +
$"\t\t\t{name} = new List<{elemCsType}>();\n" +
$"\t\t\tfor (int i = 0; i < {camel}Count; i++)\n" +
"\t\t\t{\n" +
$"\t\t\t\t{name}.Add({readElemExpr});\n" +
"\t\t\t}\n" +
"\t\t}\n" +
"\t\telse\n" +
"\t\t{\n" +
$"\t\t\t{name} = null;\n" +
"\t\t}\n";
}
/// <summary>生成普通 List&lt;T&gt; 的 Serialize 片段(writer.Write 直接写元素)</summary>
public static string GenListSerialize(string name)
{
return
$"\t\tif ({name} == null || {name}.Count == 0)\n" +
"\t\t{\n" +
"\t\t\twriter.Write(0);\n" +
"\t\t}\n" +
"\t\telse\n" +
"\t\t{\n" +
$"\t\t\twriter.Write({name}.Count);\n" +
$"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n" +
"\t\t\t{\n" +
$"\t\t\t\twriter.Write({name}[i]);\n" +
"\t\t\t}\n" +
"\t\t}\n";
}
private static string GenVectorListDeserialize(string name)
{
var camel = StringExtensions.ToCamelCase(name);
return
$"\t\tvar {camel}Count = reader.ReadInt32();\n" +
$"\t\tif ({camel}Count > 0)\n" +
"\t\t{\n" +
$"\t\t\t{name} = new List<List<float>>();\n" +
$"\t\t\tfor (int i = 0; i < {camel}Count; i++)\n" +
"\t\t\t{\n" +
"\t\t\t\tvar tempList = new List<float>();\n" +
"\t\t\t\tvar tempListCount = reader.ReadInt32();\n" +
"\t\t\t\tfor (int j = 0; j < tempListCount; j++)\n" +
"\t\t\t\t{\n" +
"\t\t\t\t\ttempList.Add(reader.ReadSingle());\n" +
"\t\t\t\t}\n" +
$"\t\t\t\t{name}.Add(tempList);\n" +
"\t\t\t}\n" +
"\t\t}\n" +
"\t\telse\n" +
"\t\t{\n" +
$"\t\t\t{name} = null;\n" +
"\t\t}\n";
}
private static string GenVectorListSerialize(string name)
{
return
$"\t\tif ({name} == null || {name}.Count == 0)\n" +
"\t\t{\n" +
"\t\t\twriter.Write(0);\n" +
"\t\t}\n" +
"\t\telse\n" +
"\t\t{\n" +
$"\t\t\twriter.Write({name}.Count);\n" +
$"\t\t\tfor (int i = 0; i < {name}.Count; i++)\n" +
"\t\t\t{\n" +
$"\t\t\t\twriter.Write({name}[i].Count);\n" +
$"\t\t\t\tfor (int j = 0; j < {name}[i].Count; j++)\n" +
"\t\t\t\t{\n" +
$"\t\t\t\t\twriter.Write({name}[i][j]);\n" +
"\t\t\t\t}\n" +
"\t\t\t}\n" +
"\t\t}\n";
}
}
}