关于游戏本地数据Excel编程工具转换 --- 2

10 篇文章 0 订阅
3 篇文章 0 订阅

Excel编程工具转换CShap

好的,我们继续上一章。
前一章我们已经把需要的数据缓存起来了,我们现在开始读表,把表中的数据拿出来缓存到对象里面去,所以,我们得需要一个对象下列代码:

[Serializable]
public class DataSvo
    {
        private Dictionary<string, Dictionary<string, List<Tuple<Type, string, string, object>>>> m_dataDictionary = new Dictionary<string, Dictionary<string, List<Tuple<Type, string, string, object>>>>();

        public Dictionary<string, Dictionary<string, List<Tuple<Type, string, string, object>>>> DataDictionary { get => m_dataDictionary; set => m_dataDictionary = value; }

        public void AddData(string className, Tuple<Type, string, string, object> data, string index)
        {
            string classFomatName = className;
            if (!DataDictionary.ContainsKey(classFomatName))
            {
                Dictionary<string, List<Tuple<Type, string, string, object>>> m_data = new Dictionary<string, List<Tuple<Type, string, string, object>>>()
                {
                    { index, new List<Tuple<Type,string, string, object>>() { data } }
                };
                DataDictionary.Add(classFomatName, m_data);
            }
            else
            {
                if (DataDictionary[classFomatName].ContainsKey(index))
                {
                    DataDictionary[classFomatName][index].Add(data);
                }
                else
                {
                    DataDictionary[classFomatName].Add(index, new List<Tuple<Type, string, string, object>>() { data });
                }
            }
        }
    }

我们的对象里面包含一个字典,这个字典里面缓存将来以及现在需要的所有数据,以类名做Key,并且标记为可序列化。[Serializable]

OK,走到这里,我们开始看看 XlsxReadResult(InitSheetClass sheetClass)这个方法吧。这个方法就是开始读工作表,但是此时我们不需要读第一张sheet了,因为我们在前面已经缓存到了 InitSheetClass这个对象里面。

private void XlsxReadResult(InitSheetClass sheetClass)
        {
            //这边会把所有的信息全部读取出来,并且放进去字符串里面
            //这里面包含所有的信息表格,一个文件的sheetClass
            Dictionary<int, Tuple<string, string, string>> data_x_type = new Dictionary<int, Tuple<string, string, string>>();
            if (sheetClass.Sheet_dic.Count > 0)
            {
                Dictionary<string, Tuple<bool, string>>.Enumerator tor = sheetClass.Sheet_dic.GetEnumerator();
                int forStartRowCount = 4;
                int forTypeStartRowCount = 1;
                int forTypeNameStartRow = 3;
                int forZhuShiStartRow = 2;
                int forIndex = 0;
                string className = "";
                while (tor.MoveNext())
                {
                    ISheet sheet = sheetClass.OperaterData.workBook.GetSheet(tor.Current.Key);//根据缓存下来的sheet来取对应的数据表
                    IRow row;
                    IRow row_type;
                    IRow row_type_name;
                    IRow row_type_ZhuShi;
                    className = sheetClass.ClassName[forIndex];
                    if (dataSvo.DataDictionary.ContainsKey(className + "Vo")) throw new Exception("存在相同的类!");
                    if (sheet != null)
                    {
                        data_x_type.Clear();
                        row_type = sheet.GetRow(forTypeStartRowCount);//先获取type行
                        row_type_name = sheet.GetRow(forTypeNameStartRow);//先获取type name行
                        row_type_ZhuShi = sheet.GetRow(forZhuShiStartRow);//先获取注释行
                        if (row_type != null && row_type_name != null)
                        {
                            Dictionary<int, string> m_str_Type_Name = new Dictionary<int, string>();
                            Dictionary<int, string> m_str_ZhuShi = new Dictionary<int, string>();
                            m_str_Type_Name.Clear();
                            m_str_ZhuShi.Clear();
                            int keyId = 0;
                            for (int i = 0; i < row_type_name.LastCellNum; i++)
                            {
                                string strValue = row_type_name.GetCell(i).ToString();
                                if (tor.Current.Value.Item2.Equals(strValue))
                                {
                                    keyId = i;
                                }
                                if (!string.IsNullOrEmpty(strValue)) m_str_Type_Name.Add(i, strValue);
                            }

                            for (int i = 0; i < row_type_ZhuShi.LastCellNum; i++)
                            {
                                string strValue = row_type_ZhuShi.GetCell(i).ToString();
                                if (!string.IsNullOrEmpty(strValue)) m_str_ZhuShi.Add(i, strValue);
                            }

                            for (int i = row_type.FirstCellNum; i < row_type.LastCellNum; i++)
                            {
                                string strValue = row_type.GetCell(i).ToString();
                                if (!string.IsNullOrEmpty(strValue))
                                {
                                    string typeInfoName = "";
                                    string zhushi = "";
                                    if (m_str_Type_Name.ContainsKey(i))
                                    {
                                        typeInfoName = m_str_Type_Name[i];
                                    }
                                    if (m_str_ZhuShi.ContainsKey(i))
                                    {
                                        zhushi = m_str_ZhuShi[i];
                                    }
                                    data_x_type.Add(i, new Tuple<string, string, string>(typeInfoName, zhushi, strValue));
                                }
                            }
                            if (data_x_type.Count > 0)
                            {
                                //循环每一行
                                int cacheIndex = 0;
                                for (int i = forStartRowCount; i <= sheet.LastRowNum; i++)
                                {
                                    row = sheet.GetRow(i);
                                    string cacheIdKey = "";
                                    if (row != null)
                                    {
                                        //循环每一个格子
                                        ICell cell;
                                        for (int c = 0; c < row.LastCellNum; c++)
                                        {
                                            cell = row.GetCell(c);
                                            if (tor.Current.Value.Item1 && c == keyId)
                                            {
                                                cacheIdKey = cacheIndex.ToString();
                                            }
                                            else if (!tor.Current.Value.Item1 && cacheIdKey == "")
                                            {
                                                cacheIdKey = cell.ToString();
                                            }
                                            if (data_x_type.ContainsKey(c))//只有定义了类型才会反序列去读取 
                                            {
                                                string type_string = data_x_type[c].Item3.ToLowerInvariant();
                                                Type typ = null;
                                                //AddData(string className, Tuple<Type, object> data, int index)  = Type.GetType("system."+type,true,true);
                                                Tuple<Type, string, string, object> data;
                                                object objParm = null;
                                                switch (type_string.ToLowerInvariant())
                                                {
                                                    case "int":
                                                        typ = typeof(int);
                                                        objParm = int.Parse(cell.ToString());
                                                        break;
                                                    case "string":
                                                        typ = typeof(string);
                                                        objParm = cell.ToString();
                                                        break;
                                                    case "array1|string":
                                                        typ = typeof(string[]);
                                                        //这里需要才分出来
                                                        string strData = cell.ToString();
                                                        objParm = strData.Split('|');
                                                        break;
                                                    case "uint":
                                                        typ = typeof(uint);
                                                        objParm = uint.Parse(cell.ToString());
                                                        break;
                                                    case "float":
                                                        typ = typeof(float);
                                                        objParm = float.Parse(cell.ToString());
                                                        break;
                                                    default:
                                                        break;
                                                }
                                                data = new Tuple<Type, string, string, object>(typ, data_x_type[c].Item1, data_x_type[c].Item2, objParm);

                                                dataSvo.AddData(className, data, cacheIdKey);
                                            }
                                        }
                                        cacheIndex++;
                                    }
                                }
                            }
                        }
                    }
                    if(strGele != null) { strGele("正在序列化类:" + className); }
                    forIndex++;
                }
            }
            if (updateProgressDelegate != null) { updateProgressDelegate(); }
        }

上面的代码应该不难理解,我也没有整理过代码,就这样放出来了,最原始的思路也许是最容易理解的。

上面我会把前四行的数据取出来和有对应数据的格子 index。然后从指定的行开始遍历,包括格子,遍历完的数据全部塞入字典里面,放入我们可序列化的对象里面,做完这一切了,我们就可以把它去做二进制的序列化了。序列化需要用到 BinaryFormatter 这个对象,具体怎么去序列化就不用阐述了。然后我们还要写出CShap文件,下面代码:

private void WriteCShapFile()
        {
            if (dataSvo != null && dataSvo.DataDictionary.Count > 0)
            {
                FileStream fileStream = null;
                string path = Directory.GetCurrentDirectory() + "/dataVo/";
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                Dictionary<string, Dictionary<string, List<Tuple<Type, string, string, object>>>>.Enumerator data_All = dataSvo.DataDictionary.GetEnumerator();
                StringBuilder stringBuilder = new StringBuilder();
                while (data_All.MoveNext())
                {
                    string className = data_All.Current.Key;
                    using (fileStream = new FileStream(path + className + ".cs", FileMode.Create))
                    {
                        Dictionary<string, List<Tuple<Type, string, string, object>>> child_data = data_All.Current.Value;
                        if (!string.IsNullOrEmpty(className) && child_data != null)
                        {
                            stringBuilder.Length = 0;
                            stringBuilder.AppendLine("using System;");
                            stringBuilder.AppendLine("[Serializable]");
                            stringBuilder.AppendLine("public class " + className + "\n{");
                            Dictionary<string, List<Tuple<Type, string, string, object>>>.Enumerator child_tor_data = child_data.GetEnumerator();
                            while (child_tor_data.MoveNext())
                            {
                                List<Tuple<Type, string, string, object>> list_local = child_tor_data.Current.Value;
                                for (int ty = 0; ty < list_local.Count; ty++)
                                {
                                    stringBuilder.AppendLine("      private " + list_local[ty].Item1.FullName + " " + list_local[ty].Item2.ToLowerInvariant() + ";");
                                    stringBuilder.AppendLine("      /// <summary> " + list_local[ty].Item3 + " </summary>");
                                    stringBuilder.AppendLine("      public " + list_local[ty].Item1.FullName + " " + GetFirstUpperStr(list_local[ty].Item2) + "\n      {");
                                    stringBuilder.AppendLine("          get { return " + list_local[ty].Item2.ToLowerInvariant() + "; }");
                                    stringBuilder.AppendLine("          set { " + list_local[ty].Item2.ToLowerInvariant() + " = value;}");
                                    stringBuilder.AppendLine("      }");
                                }
                                break;//只写一次
                            }
                            stringBuilder.AppendLine("}");
                        }
                        string str = stringBuilder.ToString();
                        byte[] writeByte = Encoding.UTF8.GetBytes(str);
                        fileStream.Write(writeByte, 0, writeByte.Length);
                        fileStream.Flush();
                    }
                    if(strGele != null) { strGele("正在写出类:" + className); }
                    if(updateProgressDelegate != null) { updateProgressDelegate(); }
                }
            }
            //这里开始写出二进制文件
        }

OK,结束了,也不是很难,之前想在Unity编辑器实现的,不过Unity编辑器考虑到性能问题,卡顿严重,就使用了C#的窗口程序来实现了,不过我把它封装成DLL的类库了。

这里写图片描述

然后我们在Unity 里面通过C#反射来调用

public Dictionary<int,T> GetDataByClass<T>()
    {
        if (!DataSVOS.isDeserialize) { return null; }
        Dictionary<int, T> result_dic = new Dictionary<int, T>();
        Assembly ably = Assembly.GetExecutingAssembly();
        Type type = typeof(T);
        if (DataSVOS.MDataSvo.DataDictionary.ContainsKey(type.Name))
        {
            PropertyInfo[] propertyInfos = type.GetProperties();
            Dictionary<string, PropertyInfo> property_dic = new Dictionary<string, PropertyInfo>();

            for (int i = 0; i < propertyInfos.Length; i++)
            {
                property_dic[propertyInfos[i].Name.ToLowerInvariant()] = propertyInfos[i];
            }
            Dictionary<string, List<SerialzeData.Tuple<Type, string, string, object>>>.Enumerator data_tor = DataSVOS.MDataSvo.DataDictionary[type.Name].GetEnumerator();
            while (data_tor.MoveNext())
            {
                object classObject = ably.CreateInstance(type.Name);//每次创建一个实例
                for (int i = 0; i < data_tor.Current.Value.Count; i++)
                {
                    string keyNe = data_tor.Current.Value[i].Item2.ToLowerInvariant();
                    if (property_dic.ContainsKey(keyNe))
                    {
                        PropertyInfo info = property_dic[keyNe];
                        info.SetValue(classObject, data_tor.Current.Value[i].Item4, null);
                        //if (info.PropertyType.Name == "String")
                        //{
                        //    info.SetValue(classObject, data_tor.Current.Value[i].Item4, null);
                        //}
                        //else
                        //{
                        //    //Type conver = data_tor.Current.Value[i].Item1;
                        //    object converSucceedObj = Convert.ChangeType(data_tor.Current.Value[i].Item4, data_tor.Current.Value[i].Item1);
                        //    Type conver = data_tor.Current.Value[i].Item1;
                        //    MethodInfo methodInfo = conver.GetMethod("CompareTo", new Type[] { typeof(object) });//反射获取类型转换的parse方法
                        //    if (methodInfo != null)
                        //    {
                        //        System.Object obj = Activator.CreateInstance(conver);//创建出数据类型
                        //        
                        //        BindingFlags flags = System.Reflection.BindingFlags.Public | BindingFlags.Static | System.Reflection.BindingFlags.Instance;
                        //        if (data_tor.Current.Value[i].Item4 == null)
                        //        {
                        //            info.SetValue(classObject, null, null);
                        //        }
                        //        else
                        //        {
                        //            object[] parameters = new object[] { converSucceedObj };//把参数放进数组里面
                        //            object result = methodInfo.Invoke(obj,flags,Type.DefaultBinder, parameters,null);
                        //            Console.WriteLine(result);
                        //        }
                        //    }
                        //    else
                        //    {
                        //        throw new Exception("get parse is null!");
                        //    }

                        //}

                    }
                }
                result_dic.Add(int.Parse(data_tor.Current.Key), (T)classObject);
            }
        }
        return result_dic;
    }

当然这边最好在第一次启动的时候就把数据初始化完毕,然后就不会每次都反射调用反序列化数据了。

shuju

然后我们可以看到,数据是已经读取出来了。Game Over!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值