Ejemplo n.º 1
0
        public static string ExportCS(string codeExportDir, string configExportDir)
        {
            // 目录清理
            if (Directory.Exists(configExportDir))
            {
                new DirectoryInfo(configExportDir).GetFiles().ToList <FileInfo>().ForEach(fi => { fi.Delete(); });
            }
            else
            {
                Directory.CreateDirectory(configExportDir);
            }
            if (!Directory.Exists(codeExportDir))
            {
                Directory.CreateDirectory(codeExportDir);
            }
            new DirectoryInfo(codeExportDir).GetFiles("data_*.cs").ToList <FileInfo>().ForEach(fi => { fi.Delete(); });
            new DirectoryInfo(codeExportDir).GetFiles("formula_*.cs").ToList <FileInfo>().ForEach(fi => { fi.Delete(); });

            // stream加载的接口
            Dictionary <string, string> typestream_read = new Dictionary <string, string>();

            typestream_read.Add("int", "ReadInt32");
            typestream_read.Add("string", "ReadString");
            typestream_read.Add("double", "ReadDouble");
            typestream_read.Add("int32", "ReadInt32");

            // 类型转换
            Dictionary <string, string> typeconvert = new Dictionary <string, string>();

            typeconvert.Add("int", "int");
            typeconvert.Add("int32", "int");
            typeconvert.Add("string", "string");
            typeconvert.Add("double", "double");
            typeconvert.Add("[]int", "int[]");
            typeconvert.Add("[]int32", "int[]");
            typeconvert.Add("[]string", "string[]");
            typeconvert.Add("[]double", "double[]");
            typeconvert.Add("[]float", "float[]");

            // 索引类型转换
            Dictionary <string, string> mapTypeConvert = new Dictionary <string, string>();

            mapTypeConvert.Add("int", "int");
            mapTypeConvert.Add("float", "float");
            mapTypeConvert.Add("int32", "int");
            mapTypeConvert.Add("string", "string");
            mapTypeConvert.Add("float32", "float");
            mapTypeConvert.Add("double", "double");

            int           goWriteCount = 0;
            List <string> loadfuncs    = new List <string>();
            List <string> clearfuncs   = new List <string>();
            List <string> savefuncs    = new List <string>();

            // 写公式
            foreach (var formula in formulaContents)
            {
                File.WriteAllText(codeExportDir + "formula_" + formula.Key.ToLower() + ".cs", formula.Value, new UTF8Encoding(false));
                Interlocked.Increment(ref goWriteCount);
                // lock (loadfuncs) loadfuncs.Add("loadFormula" + formula.Key);
            }

            List <string> results = new List <string>();

            // 写cs
            foreach (var data in datas.Values)
            {
                ThreadPool.QueueUserWorkItem(ooo =>
                {
                    string bigname         = data.name.Substring(0, 1).ToUpper() + data.name.Substring(1);
                    string tableClassName  = bigname + "Table";
                    string configClassName = bigname + "Config";
                    string groupClassName  = bigname + "TableGroup";
                    string jsonfilename    = bigname.ToLower();

                    StringBuilder sb = new StringBuilder();
                    sb.Append("using System;\r\n");
                    sb.Append("using UnityEngine;\r\n");
                    sb.Append("using System.Collections;\r\n");
                    sb.Append("using System.Collections.Generic;\r\n");

                    // 使用Newtonsoft的json解析
                    // sb.Append("#if UNITY_EDITOR\r\n");
                    // sb.Append("using Newtonsoft.Json;\r\n");
                    // sb.Append("#endif\r\n");

                    // stream 需要io
                    sb.Append("using System.IO;\r\n");

                    // 使用c#热更的引用
                    // sb.Append("#if !UNITY_EDITOR\r\n");
                    // sb.Append("using SuperMobs.CoreExport;\r\n");
                    // sb.Append("#endif\r\n");
                    sb.Append("\r\n");

                    // 扩展Config类统一获取某个表的实例对象
                    sb.Append("public partial class Config {\r\n");

                    // 获取方法
                    sb.Append("\tstatic " + tableClassName + " _" + tableClassName + ";\r\n");
                    sb.Append("\tpublic static " + tableClassName + " Get" + tableClassName + "(){\r\n");
                    sb.Append(string.Format("\tif({0} == null) Load{1}();\r\n", "_" + tableClassName, tableClassName));
                    sb.Append("\t\treturn _" + tableClassName + ";\r\n");
                    sb.Append("\t}\r\n");

                    // 加载方法
                    sb.Append("\tpublic static void Load" + tableClassName + "(){\r\n");

                    sb.Append(string.Format("\tif(_{0} != null) return;\r\n\r\n", tableClassName));

                    //sb.Append(string.Format("\t\tvar json = Service.Get<ILoaderService>().LoadConfig(\"{0}\");\r\n", data.name));
                    //sb.Append(string.Format("\t\t{0} = LitJson.JsonMapper.ToObject<{1}>(json);\r\n", "_" + tableClassName, tableClassName));
                    //sb.Append(string.Format("\t\t{0} = JsonConvert.DeserializeObject<{1}>(json);\r\n","_"+tableClassName,tableClassName));

                    // ! 二进制加载方法
                    sb.Append("\tstring filename=\"" + jsonfilename + "\";\r\n");

                    // sb.Append("\t#if UNITY_EDITOR\r\n");
                    // sb.Append("\tstring js_path=PATH_ASSETS_FOLDER+\"/\" + filename + \".bytes\";\r\n");
                    // sb.Append("\tbyte[] bys = ExportUtils.LoadConfigBytes(js_path);\r\n");
                    // sb.Append("\t#else\r\n");
                    sb.Append("\tbyte[] bys = delegateLoadConfigBytes(filename);\r\n");
                    // sb.Append("\t#endif\r\n");

                    sb.Append(string.Format("\t_{0} = new {0}();\r\n", tableClassName));
                    sb.Append(string.Format("\t_{0}.Init(bys);\r\n", tableClassName));

                    sb.Append("\t}\r\n");

                    // 清理方
                    sb.Append(string.Format("\tpublic static void Clear{0} () {{\r\n", tableClassName));
                    sb.Append(string.Format("\t\t_{0} = null;\r\n", tableClassName));
                    sb.Append("\t}\r\n");
                    lock (clearfuncs) clearfuncs.Add("Config.Clear" + tableClassName);

                    // 保存一次stream二进制流接口
                    sb.Append(string.Format("\tpublic static void Save{0} () {{\r\n", tableClassName));
                    sb.Append("\tstring filename=\"" + jsonfilename + "\";\r\n");
                    sb.Append("\tList<string> dirs = new List<string>(Directory.GetDirectories(PATH_ASSETS_FOLDER));\r\n");
                    sb.Append("\tdirs.Add(PATH_ASSETS_FOLDER);\r\n");

                    sb.Append("\tforeach(var dir in dirs){\r\n");
                    sb.Append("\t\tstring js_path=dir+\"/\" + filename + \".json\";\r\n");
                    sb.Append("\t\tif(File.Exists(js_path) == false) continue; \r\n");
                    sb.Append("\t\tstring js=delegateLoadConfigJson(js_path);\r\n");
                    sb.Append(string.Format("\t\tvar val= Newtonsoft.Json.JsonConvert.DeserializeObject<{0}>(js);\r\n", tableClassName));
                    sb.Append("\t\tvar bys=val.ToBytes();\r\n");
                    sb.Append("\t\tstring save_path=dir+\"/\" + filename + \".bytes\";\r\n");
                    sb.Append("\t\tFile.WriteAllBytes(save_path,bys);\r\n");
                    sb.Append("\t}\r\n");
                    sb.Append("\t}\r\n");

                    lock (savefuncs) savefuncs.Add("Config.Save" + tableClassName);
                    sb.Append("}\r\n"); // config扩展接口类结束

                    //------

                    // group class
                    sb.Append("public class " + groupClassName + " : StreamConfig " + " {\r\n");
                    foreach (var g in data.groups)
                    {
                        // --------------------------------
                        sb.Append("\tpublic ");
                        //  Dictionary<int,Dic<int,Dic<int,[]int>>>
                        foreach (string t in g.Value)
                        {
                            sb.Append("Dictionary<" + mapTypeConvert[typeconvert[data.types[data.keys.IndexOf(t)]]] + ",");
                        }
                        //这里先全部用string 现在用 litjson 在下面类型判断的时候再去是否加tostring
                        // sb.Append("Dictionary<string" + ",");
                        sb.Append("int[]");
                        foreach (var t in g.Value)
                        {
                            sb.Append(">");
                        }

                        sb.Append(" ");

                        // Group的名称,合并参数后的,例如多个参数 : a|b > a_b
                        var gk = g.Key.Substring(0, 1).ToUpper() + g.Key.Replace("|", "_").Substring(1);

                        sb.Append(gk + ";\r\n");
                        // --------------------------------
                        // per group value
                    }

                    // ! 根据需要跳过的某个位置的group获取类型嵌套的类型
                    Func <int, string[], string> _func_get_group_type_by_index = (_gi, _gv) => {
                        string gt = "";
                        for (int i = 0; i < _gv.Length; i++)
                        {
                            if (i < _gi)
                            {
                                continue;
                            }
                            string t = _gv[i];
                            gt      += ("Dictionary<" + mapTypeConvert[typeconvert[data.types[data.keys.IndexOf(t)]]] + ",");
                            //这里先全部用string 现在用 litjson 在下面类型判断的时候再去是否加tostring
                            // sb.Append("Dictionary<string" + ",");
                        }
                        gt += "int[]";
                        for (int i = 0; i < _gv.Length; i++)
                        {
                            if (i < _gi)
                            {
                                continue;
                            }
                            gt += ">";
                        }
                        return(gt);
                    };
                    Func <int, string[], string> _func_get_group_keytype_by_index = (_gi, _gv) => {
                        string gk = "";
                        for (int i = 0; i < _gv.Length; i++)
                        {
                            if (i < _gi)
                            {
                                continue;
                            }
                            string t = _gv[i];
                            gk       = mapTypeConvert[typeconvert[data.types[data.keys.IndexOf(t)]]];
                            break;
                        }
                        return(gk);
                    };

                    // ! > stream 读取
                    sb.Append("\tpublic override void FromStream(BinaryReader br){\r\n");
                    // 先定义一个长度
                    sb.Append("\t\tint _count = 0;\r\n");

                    foreach (var g in data.groups)
                    {
                        // Group的名称,合并参数后的,例如多个参数 : a|b > a_b
                        var gk = g.Key.Substring(0, 1).ToUpper() + g.Key.Replace("|", "_").Substring(1);

                        // 先获取这个group的类型
                        string gt = _func_get_group_type_by_index(0, g.Value);

                        // 初始化group长度
                        sb.Append("\t\t_count=br.ReadInt32();\r\n");
                        sb.Append("\t\t" + gk + "=new " + gt + "(_count);\r\n");
                        sb.Append("\t\tfor(int i=0; i < _count; i++){\r\n");
                        int _value_num = g.Value.Length;
                        if (_value_num == 1)
                        {
                            string _k = _func_get_group_keytype_by_index(0, g.Value);
                            sb.Append(string.Format("\t\t\t{0} k" + " = br.{1}();\r\n", _k, typestream_read[_k]));
                            sb.Append("\t\t\tint[] v" + "=null;\r\n");
                            sb.Append("\t\t\tReadArray(br,ref v" + ");\r\n");
                            sb.Append("\t\t\t" + gk + "[k]=v;\r\n");
                        }
                        else
                        {
                            for (int i = 0; i < _value_num; i++)
                            {
                                // key
                                string _k = _func_get_group_keytype_by_index(i, g.Value);
                                sb.Append(string.Format("\t\t\t{0} k" + i + " = br.{1}();\r\n", _k, typestream_read[_k]));

                                if (i != _value_num - 1)
                                {
                                    // 还没到最后
                                    sb.Append("\t\t\tint _count" + i + "=br.ReadInt32();\r\n");
                                    string _gt = _func_get_group_type_by_index(i + 1, g.Value);
                                    sb.Append("\t\t\t" + _gt + " v" + i + " = new " + _gt + "(_count" + i + ");\r\n");
                                    sb.Append("\t\t\tfor(int i" + i + "=0; i" + i + " < _count" + i + "; i" + i + "++) {\r\n");
                                }
                                else
                                {
                                    // 最后一个是int[]
                                    sb.Append("\t\t\tint[] v" + i + "=null;\r\n");
                                    sb.Append("\t\t\tReadArray(br,ref v" + i + ");\r\n");
                                }
                            }
                            // 加反括号和设置v
                            for (int i = _value_num - 1; i >= 1; i--)
                            {
                                sb.Append("\t\t\tv" + (i - 1) + "[k" + (i) + "]=v" + (i) + ";\r\n");
                                sb.Append("}\r\n");
                            }

                            // 设置最外面那个字典是第一个值
                            sb.Append("\t\t\t" + gk + "[k0]=v0;\r\n");
                        }
                        sb.Append("}\r\n");
                    }
                    sb.Append("}\r\n");


                    // ! > stream 写入
                    sb.Append("\tpublic override void ToStream(BinaryWriter bw){\r\n");
                    foreach (var g in data.groups)
                    {
                        // Group的名称,合并参数后的,例如多个参数 : a|b > a_b
                        string gk = g.Key.Substring(0, 1).ToUpper() + g.Key.Replace("|", "_").Substring(1);
                        string gt = _func_get_group_type_by_index(0, g.Value);

                        // 先写长度
                        sb.Append(string.Format("\t\tif({0} == null) {0} = new {1}();\r\n", gk, gt));
                        sb.Append("\t\t" + "bw.Write(" + gk + ".Count" + ");\r\n");
                        // 开始写内容
                        int _value_num = g.Value.Length;
                        sb.Append("\t\tforeach(var item1 in " + gk + ") {\r\n");
                        sb.Append("\t\tbw.Write(item1.Key);\r\n");
                        if (_value_num == 1)
                        {
                            sb.Append("\t\tint[] v=item1.Value;\r\n");
                            sb.Append("\t\tWriteArray(bw,ref v);\r\n");
                        }
                        else if (_value_num > 1)
                        {
                            sb.Append("\t\tbw.Write(item1.Value.Count);\r\n");
                            // 需要多次foreach去写入
                            for (int i = 2; i <= _value_num; i++)
                            {
                                sb.Append("\t\t\tforeach(var item" + i + " in item" + (i - 1) + ".Value){\r\n");
                                sb.Append("\t\t\tbw.Write(item" + i + ".Key" + ");\r\n");
                                if (i != _value_num)
                                {
                                    // 不是最后一个继续foreach,所以还是写长度
                                    sb.Append("\t\t\tbw.Write(item" + i + ".Value.Count" + ");\r\n");
                                }
                                else
                                {
                                    // 最后一个设置那个int[]了
                                    sb.Append("\t\t\tint[] v=item" + i + ".Value;\r\n");
                                    sb.Append("\t\t\tWriteArray(bw,ref v);\r\n");
                                }
                            }

                            // 再加那个反括号
                            for (int i = 2; i <= _value_num; i++)
                            {
                                sb.Append("\t\t}\r\n");
                            }
                        }
                        else
                        {
                            throw new Exception("the group is error value size is not morethan 1    group =" + gk);
                        }
                        sb.Append("\t}\r\n");
                    }
                    sb.Append("}\r\n");


                    sb.Append("}\r\n");

                    // config class
                    sb.Append("public class " + configClassName + " : StreamConfig " + " {\r\n");
                    for (int i = 0; i < data.keys.Count; i++)
                    {
                        sb.Append("\tpublic " + typeconvert[data.types[i]] + " " + data.keys[i].Substring(0, 1).ToUpper() + data.keys[i].Substring(1) + "; " + "// " + data.keyNames[i] + "\r\n");
                    }
                    // ! > steam加载 读取
                    sb.Append("\tpublic override void FromStream(BinaryReader br){\r\n");
                    for (int i = 0; i < data.keys.Count; i++)
                    {
                        string t = typeconvert[data.types[i]];
                        string n = data.keys[i].Substring(0, 1).ToUpper() + data.keys[i].Substring(1);
                        if (t.Contains("[]"))
                        {
                            // 数组
                            sb.Append("\t" + "ReadArray(br,ref " + n + ");\r\n");
                        }
                        else
                        {
                            sb.Append("\t" + n + "=br." + typestream_read[data.types[i]] + "();\r\n");
                        }
                    }
                    sb.Append("}\r\n");
                    // ! > stream 写入
                    sb.Append("\tpublic override void ToStream(BinaryWriter bw){\r\n");
                    for (int i = 0; i < data.keys.Count; i++)
                    {
                        string t = typeconvert[data.types[i]];
                        string n = data.keys[i].Substring(0, 1).ToUpper() + data.keys[i].Substring(1);
                        if (t.Contains("[]"))
                        {
                            sb.Append("\t" + "WriteArray(bw,ref " + n + ");\r\n");
                        }
                        else if (t.Contains("string"))
                        {
                            sb.Append("\tbw.Write(!string.IsNullOrEmpty(" + n + ") ? " + n + ":\"\"" + ");\r\n");
                        }
                        else
                        {
                            sb.Append("\tbw.Write(" + n + ");\r\n");
                        }
                    }
                    sb.Append("}\r\n");


                    sb.Append("}\r\n");

                    // table class
                    sb.Append("// " + string.Join(",", data.files) + "\r\n");
                    sb.Append("public class " + tableClassName + " : StreamConfig " + " {\r\n");
                    sb.Append("\tpublic string Name;\r\n");
                    sb.Append(string.Format("\tpublic Dictionary<int, {0}> _Datas;\r\n", configClassName));
                    sb.Append(string.Format("\tpublic {0} _Group;\r\n", groupClassName));

                    // 写每一个group的缓存字典数据
                    foreach (var g in data.groups)
                    {
                        // Group的名称,合并参数后的
                        var gk = g.Key.Substring(0, 1).ToUpper() + g.Key.Replace("|", "_").Substring(1);
                        // --------------------------------
                        sb.Append("\tprivate ");
                        sb.Append("Dictionary<string" + ",");
                        sb.Append(configClassName + "[]> " + gk + "_Cached" + " = new ");
                        sb.Append("Dictionary<string" + "," + configClassName + "[]>();\r\n");
                        // --------------------------------
                    }

                    // 增加二进制流动态读取的结构和对象
                    sb.Append("\tprivate Dictionary<int, int> _Data_Pos;\r\n");
                    sb.Append("\tprivate BinaryReader _br;\r\n");
                    sb.Append("\tprivate long _start_data_pos;\r\n");
                    sb.Append("\tprivate byte[] _bytes;\r\n");
                    sb.Append("\tprivate bool isInitAll;\r\n");
                    sb.Append("\tpublic int Count;\r\n");

                    if (data.funcDatas.Count > 0)
                    {
                        foreach (var item in data.funcDatas)
                        {
                            var value = item.Value;
                            sb.Append(string.Format("\tprivate Dictionary<int, Action<{0}>> _data_{1};\r\n", value.funcType, value.funcName));
                        }
                    }

                    sb.Append(string.Format("\tpublic Dictionary<int, {0}> GetFullDatas()", configClassName) + "{\r\n");
                    sb.Append("\t\tif (isInitAll == false){ \r\n");
                    sb.Append("\t\t\tisInitAll = true;\r\n");
                    sb.Append("\t\t\tforeach (var item in _Data_Pos){ ReadConfig(item.Key); }\r\n");
                    sb.Append("\t}\r\n");
                    sb.Append("\t\treturn _Datas;\r\n");
                    sb.Append("}\r\n");

                    sb.Append("\tpublic void Init(byte[] bs){\r\n");
                    sb.Append("\t\t_bytes = bs;\r\n");
                    sb.Append("\t\t_br = new BinaryReader(new MemoryStream(bs));\r\n");
                    sb.Append("\t\tthis.FromBytes(bs);\r\n");
                    sb.Append("}\r\n");

                    sb.Append("\t" + configClassName + " ReadConfig(int id) { \r\n");
                    sb.Append("\t\t" + configClassName + " cfg = null;\r\n");
                    sb.Append("\t\tif (_Datas.TryGetValue(id, out cfg)) return cfg;\r\n");
                    sb.Append("\t\tif (_Data_Pos.ContainsKey(id) == false) return null;\r\n");
                    sb.Append("\t\tcfg = new " + configClassName + "();\r\n");
                    sb.Append("\t\tint p = _Data_Pos[id];\r\n");
                    sb.Append("\t\t_br.BaseStream.Position = _start_data_pos + p;\r\n");
                    sb.Append("\t\tcfg.FromStream(_br);\r\n");
                    sb.Append("\t\t_Datas[id] = cfg; \r\n");
                    sb.Append("\t\treturn cfg;\r\n");
                    sb.Append("}\r\n");

                    // ! > stream 加载
                    sb.Append("\tpublic override void FromStream(BinaryReader br){\r\n");
                    sb.Append("\t\tName=br.ReadString();\r\n");
                    sb.Append("\t\t_Group=new " + groupClassName + "();\r\n");
                    sb.Append("\t\t_Group.FromStream(br);\r\n");
                    sb.Append("\t\tint _datas_count=br.ReadInt32();\r\n");
                    sb.Append("\t\tCount = _datas_count;\r\n");
                    sb.Append(string.Format("\t\t_Datas=new Dictionary<int, {0}>();\r\n", configClassName));
                    sb.Append("\t\t_Data_Pos = new Dictionary<int, int>(_datas_count);\r\n");
                    sb.Append("\t\tfor(int i=0; i < _datas_count; i++){\r\n");
                    sb.Append("\t\tint _id=br.ReadInt32();\r\n");
                    sb.Append("\t\tint _pos=br.ReadInt32();\r\n");
                    sb.Append("\t\t_Data_Pos[_id] = _pos;\r\n");
                    sb.Append("\t\t}\r\n");
                    sb.Append("\t\t_start_data_pos = br.BaseStream.Position;\r\n");
                    sb.Append("}\r\n");

                    // ! < stream 写入
                    sb.Append("\tpublic override void ToStream(BinaryWriter bw){\r\n");
                    sb.Append("\t\tbw.Write(Name);\r\n");
                    sb.Append("\t\t_Group.ToStream(bw);\r\n");
                    sb.Append("\t\tbw.Write(_Datas.Count);\r\n");

                    sb.Append("\t\tList<int> _ids = new List<int>();\r\n");
                    sb.Append("\t\tList<int> _idlens = new List<int>();\r\n");
                    sb.Append("\t\tList<byte[]> _idbys = new List<byte[]>();\r\n");
                    sb.Append("\t\tint _idpos = 0;\r\n");
                    sb.Append("\t\tforeach(var item in _Datas){\r\n");
                    sb.Append("\t\t\t_ids.Add(item.Key);\r\n");
                    sb.Append("\t\t\tvar bs = item.Value.ToBytes();\r\n");
                    sb.Append("\t\t\t_idbys.Add(bs);\r\n");
                    sb.Append("\t\t\t_idlens.Add(_idpos);\r\n");
                    sb.Append("\t\t\t_idpos += bs.Length;\r\n");
                    sb.Append("\t}\r\n");

                    sb.Append("\t\tfor (int i = 0; i < _ids.Count; i++){\r\n");
                    sb.Append("\t\t\tbw.Write(_ids[i]);\r\n");
                    sb.Append("\t\t\tbw.Write(_idlens[i]);\r\n");
                    sb.Append("\t}\r\n");

                    sb.Append("\t\tfor (int i = 0; i < _ids.Count; i++){\r\n");
                    sb.Append("\t\t\tbw.Write(_idbys[i]);\r\n");
                    sb.Append("\t}\r\n");

                    sb.Append("}\r\n");

                    // get config function
                    sb.Append("public " + configClassName + " Get(int id) {\r\n");
                    sb.Append("\t\treturn ReadConfig(id);\r\n");
                    sb.Append("}\r\n");

                    if (data.funcDatas.Count > 0)
                    {
                        Console.WriteLine(data.name);
                        foreach (var item in data.funcDatas)
                        {
                            var value      = item.Value;
                            string envName = string.Format("env_{0}_{1}_cs", data.name, value.funcName);
                            DataStruct env = null;
                            foreach (var e in datas)
                            {
                                if (e.Value.name == envName)
                                {
                                    env = e.Value;
                                    env.dataContent.Sort(CmpLen);
                                    break;
                                }
                            }
                            sb.Append(string.Format("\tpublic Action<{0}> Get_{1}(int id) {{\r\n", value.funcType, value.funcName));
                            sb.Append(string.Format("\t\tif (_data_{0} == null) {{\r\n", value.funcName));
                            sb.Append(string.Format("\t\t\t_data_{0} = new Dictionary<int, Action<{1}>>();\r\n", value.funcName, value.funcType));
                            var list = item.Value.data;
                            for (int i = 0; i < list.Count; ++i)
                            {
                                var id = data.dataContent[i][0];
                                // sb.Append(string.Format("\t\t\t/* {0} */", list[i])); // 翻译文字
                                Console.WriteLine(i + " " + id);
                                sb.Append(string.Format("\t\t\t_data_{0}[{1}] = delegate({2}) {{\r\n", value.funcName, id, value.funcTypeParam));
                                Console.WriteLine(list[i]);
                                var trans_list = list[i].Replace("\n", "").Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); // aaa=bbb;ccc=ddd+eee;
                                foreach (var line in trans_list)
                                {
                                    Console.WriteLine(line);
                                    var eqarr = line.Split('=');
                                    sb.Append(string.Format("\t\t\t\t// {0}\r\n", line));
                                    sb.Append(string.Format("\t\t\t\t{0}={1};\r\n", env.TranslateLeft(eqarr[0]), env.TranslateRight(eqarr[1])));
                                }
                                sb.Append("\t\t\t};\r\n"); // enddelegate
                            }
                            sb.Append("\t\t}\r\n");        // endif
                            sb.Append(string.Format("\t\treturn _data_{0}[id];\r\n", value.funcName));
                            sb.Append("\t}\r\n");
                            sb.Append("\r\n");
                        }
                    }

                    // group data function
                    foreach (var g in data.groups)
                    {
                        // Group的名称,合并参数后的
                        var gk = g.Key.Substring(0, 1).ToUpper() + g.Key.Replace("|", "_").Substring(1);

                        sb.Append("\tpublic " + configClassName + "[]" + " Get_" + g.Key.Replace("|", "_") + "(");
                        foreach (var t in g.Value)
                        {
                            sb.Append(mapTypeConvert[typeconvert[data.types[data.keys.IndexOf(t)]]] + " " + t.Substring(0, 1).ToUpper() + t.Substring(1) + ",");
                        }
                        sb.Remove(sb.Length - 1, 1);
                        sb.Append(") {\r\n");



                        // 优化先在cach的字典里面判断
                        string cach_key = "string.Empty";
                        foreach (var t in g.Value)
                        {
                            string vk = t.Substring(0, 1).ToUpper() + t.Substring(1);
                            cach_key += ("+" + vk + "+" + "\"_\"");
                        }
                        string cach_group_name = gk + "_Cached";
                        sb.Append("string cach_key = " + cach_key + ";\r\n");
                        sb.Append(configClassName + "[] ret;\r\n");
                        sb.Append("if(" + cach_group_name + ".TryGetValue(cach_key,out ret))\r\n");
                        sb.Append("\treturn ret;\r\n");

                        string oldDictName = "_Group." + gk;
                        string oldKeyName  = "";
                        for (int i = 0; i < g.Value.Length; i++)
                        {
                            if (i == 0)
                            {
                                sb.Append("if (" + oldDictName + ".ContainsKey(");
                                oldKeyName = g.Value[i].Substring(0, 1).ToUpper() + g.Value[i].Substring(1);
                                // ! .ToString()
                                sb.Append(oldKeyName + ") ){\r\n");
                            }
                            else
                            {
                                string tempName = "tmp" + (i - 1);
                                // ! .ToString()
                                sb.Append("var " + tempName + " = " + oldDictName + "[" + oldKeyName + "];\r\n");
                                sb.Append("if (" + tempName + ".ContainsKey(");
                                oldDictName = tempName;
                                oldKeyName  = g.Value[i].Substring(0, 1).ToUpper() + g.Value[i].Substring(1);
                                // ! .ToString()
                                sb.Append(oldKeyName + ") ){\r\n");
                            }
                        }

                        // ! .ToString()
                        sb.Append("var ids = " + oldDictName + "[" + oldKeyName + "];\r\n");
                        sb.Append("var configs = new " + configClassName + "[ids.Length];\r\n");
                        sb.Append("for (int i = 0; i < ids.Length; i++) {\r\n");
                        sb.Append("\tvar id = ids[i];\r\n");
                        sb.Append("\tconfigs[i] = Get(id);\r\n");
                        sb.Append("}\r\n");
                        // 缓存一下这次的结果
                        sb.Append("\t" + cach_group_name + "[cach_key]" + "=configs;\r\n");
                        sb.Append("return configs;\r\n");
                        for (int i = 0; i < g.Value.Length; i++)
                        {
                            sb.Append("}\r\n");
                        }

                        sb.Append("return new " + configClassName + "[0];\r\n");
                        sb.Append("}\r\n");
                    }

                    for (int i = 0; i < data.keys.Count; i++)
                    {
                        if (data.types[i] == "string" || data.types[i].StartsWith("[]"))
                        {
                            continue;
                        }
                        sb.Append("\tpublic float data_" + data.name + "_vlookup_" + (data.cols[i] + 1) + "(int id) {\r\n");
                        // ! id.ToString()
                        sb.Append("\treturn (float)(Get(id)." + data.keys[i].Substring(0, 1).ToUpper() + data.keys[i].Substring(1) + ");\r\n");
                        sb.Append("}\r\n");
                    }

                    sb.Append("}\r\n"); // table class结束

                    // ---------------------写这个table class的扩展便捷获取方法数组的SingleOne----------------------
                    sb.Append("public static class " + tableClassName + "ExternFunc" + " {\r\n");
                    sb.Append("\tpublic static " + configClassName + " SingleOne (this " + configClassName + "[] arr){ \r\n");
                    sb.Append("\t\tif(arr != null && arr.Length > 0) return arr[0];\r\n");
                    sb.Append("\t\treturn null;\r\n");
                    sb.Append("\t}\r\n");
                    sb.Append("}\r\n"); // table extern func class结束

                    File.WriteAllText(codeExportDir + "data_" + data.name + ".cs", sb.ToString());
                    Interlocked.Increment(ref goWriteCount);
                    lock (loadfuncs) loadfuncs.Add("Config.Load" + tableClassName);

                    lock (results)
                        results.Add(string.Empty);
                });
            }

            // 写json
            foreach (var data in datas.Values)
            {
                ThreadPool.QueueUserWorkItem(ooo =>
                {
                    JObject config = new JObject();
                    config["Name"] = data.name;

                    JObject datas    = new JObject();
                    config["_Datas"] = datas;
                    foreach (var line in data.dataContent)
                    {
                        JObject ll = new JObject();
                        for (int j = 0; j < data.keys.Count; j++)
                        {
                            ll[data.keys[j].TitleToUpper()] = JToken.FromObject(line[j]);
                        }
                        datas[line[0].ToString()] = ll;
                    }

                    JObject group    = new JObject();
                    config["_Group"] = group;
                    Dictionary <string, string[]> .Enumerator enumerator = data.groups.GetEnumerator();
                    while (enumerator.MoveNext())
                    {
                        group[enumerator.Current.Key.Replace("|", "_").TitleToUpper()] = new JObject();
                    }
                    foreach (var values in data.dataContent)
                    {
                        enumerator = data.groups.GetEnumerator();
                        while (enumerator.MoveNext())
                        {
                            JObject cur = group[enumerator.Current.Key.Replace("|", "_").TitleToUpper()] as JObject;
                            string key  = string.Empty;
                            for (int j = 0; j < enumerator.Current.Value.Length - 1; j++)
                            {
                                key = values[data.groupindexs[enumerator.Current.Key][j]].ToString();
                                if (cur[key] == null)
                                {
                                    cur[key] = new JObject();
                                }
                                cur = cur[key] as JObject;
                            }
                            key = values[data.groupindexs[enumerator.Current.Key][enumerator.Current.Value.Length - 1]].ToString();
                            if (cur[key] == null)
                            {
                                cur[key] = new JArray();
                            }
                            (cur[key] as JArray).Add(JToken.FromObject(values[0]));
                        }
                    }

                    StringWriter textWriter   = new StringWriter();
                    textWriter.NewLine        = "\r\n";
                    JsonTextWriter jsonWriter = new JsonTextWriter(textWriter)
                    {
                        Formatting  = Formatting.Indented,
                        Indentation = 4,
                        IndentChar  = ' '
                    };
                    new JsonSerializer().Serialize(jsonWriter, config);
                    var content = textWriter.ToString();
                    File.WriteAllText(configExportDir + data.name + ".json", content, new UTF8Encoding(false));

                    lock (results)
                        results.Add(string.Empty);
                });
            }


            // 格式化代码
            while (goWriteCount < formulaContents.Count + datas.Values.Count)
            {
                Thread.Sleep(10);
            }

            // 写加载
            loadfuncs.Sort();
            StringBuilder loadcode = new StringBuilder();

            loadcode.Append("using System;\r\n");
            loadcode.Append("using UnityEngine;\r\n");
            loadcode.Append("using System.Collections;\r\n");
            loadcode.Append("using System.Collections.Generic;\r\n");
            loadcode.Append("\r\n");

            // 扩展Config类统一获取某个表的实例对象
            loadcode.Append("public partial class Config {\r\n");

            // load all
            loadcode.Append("\tpublic static void Load() {\r\n");
            foreach (var str in loadfuncs)
            {
                loadcode.Append("\t" + str + "();\r\n");
            }
            loadcode.Append("}\r\n");

            // clear all
            clearfuncs.Sort();
            loadcode.Append("\tpublic static void Clear() {\r\n");
            foreach (var str in clearfuncs)
            {
                loadcode.Append("\t" + str + "();\r\n");
            }
            loadcode.Append("}\r\n");

            // save all
            savefuncs.Sort();
            loadcode.Append("\tpublic static void Save() {\r\n");
            foreach (var str in savefuncs)
            {
                loadcode.Append("\t" + str + "();\r\n");
            }
            loadcode.Append("}\r\n");

            loadcode.Append("}\r\n");
            File.WriteAllText(codeExportDir + "load.cs", loadcode.ToString());

            // 等待所有文件完成
            while (results.Count < datas.Values.Count * 2)
            {
                Thread.Sleep(TimeSpan.FromSeconds(0.01));
            }

            return(string.Empty);
        }