void Serialize(object obj, IEnumerable <Attribute> attributes) { if (obj == null) { return; } Type type = obj.GetType(); if (type.IsEnum) { _writer.Write(((int)obj).ToString()); } else if (type.IsValueType) { if (type == typeof(DateTime)) { _writer.Write(QuoteAndEscapeString(obj.ToString())); } else if (type == typeof(bool)) { _writer.Write(obj.ToString().ToLower()); } else { string objVal = Convert.ToString(obj, CultureInfo.InvariantCulture); _writer.Write(objVal); } } else if (type == typeof(string)) { _writer.Write(QuoteAndEscapeString((string)obj)); } else if (typeof(IDictionary).IsAssignableFrom(type)) { _writer.Write("{"); IDictionary dict = (IDictionary)obj; foreach (object key in dict.Keys) { WriteTableMember(key, dict[key], null); } _writer.Write("}"); } else if (typeof(IEnumerable).IsAssignableFrom(type)) { IEnumerable list = (IEnumerable)obj; _writer.Write("{"); bool skipNull = false; ArrayIndexMode indexMode = ArrayIndexMode.Default; LuaArrayAttribute arrayAttribute = null; if (attributes != null) { arrayAttribute = (LuaArrayAttribute)attributes.FirstOrDefault(x => x is LuaArrayAttribute); } if (arrayAttribute != null) { skipNull = arrayAttribute.SkipNull; indexMode = arrayAttribute.IndexMode; } int index = indexMode == ArrayIndexMode.ZeroBased ? 0 : 1; foreach (object item in list) { WriteTableMember(index, item, null); index++; } _writer.Write("}"); } else { _writer.Write("{"); foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { WriteTableMember(pi.Name, pi.GetValue(obj), pi.GetCustomAttributes()); } foreach (FieldInfo fi in type.GetFields(BindingFlags.Public | BindingFlags.Instance)) { WriteTableMember(fi.Name, fi.GetValue(obj), fi.GetCustomAttributes()); } _writer.Write("}"); } }
object ReadTable(Type tableType, IEnumerable <Attribute> attributes) { int startPosition = _dataReader.Cursor; int r = _dataReader.Read(); if (r != '{') { throw new ParseException($"Expects table open bracket but got {(char) r}"); } Type genericTypeDefinition = null; if (tableType.IsGenericType) { genericTypeDefinition = tableType.GetGenericTypeDefinition(); } bool isTableTypeDict = genericTypeDefinition == typeof(Dictionary <,>); Dictionary <string, MemberInfo> memberNameInfoDict = null; Type keyType = null; Type valueType = null; bool isFixedValueType = false; if (isTableTypeDict) { Type[] genericArguments = tableType.GetGenericArguments(); keyType = genericArguments[0]; valueType = genericArguments[1]; isFixedValueType = true; } else if (tableType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(tableType)) { valueType = tableType.GetGenericArguments()[0]; isFixedValueType = true; } else if (tableType.IsArray) { keyType = typeof(int); valueType = tableType.GetElementType(); isFixedValueType = true; } else { memberNameInfoDict = GetMemberNameInfoDict(tableType); } Dictionary <object, object> tableContent = new Dictionary <object, object>(); bool isSuccess = false; while ((r = _dataReader.Peek()) != -1) { SkipSpacesAndComment(); r = _dataReader.Peek(); if (r == '}') { _dataReader.Read(); isSuccess = true; break; } object key = ReadTableMemberKeyAssignment(keyType); IEnumerable <Attribute> memberAttributes = null; if (!isFixedValueType) { string keyString = key.ToString(); if (memberNameInfoDict.ContainsKey(keyString)) { MemberInfo mi = memberNameInfoDict[keyString]; if (mi is PropertyInfo) { valueType = ((PropertyInfo)mi).PropertyType; } else { valueType = ((FieldInfo)mi).FieldType; } if (valueType.IsArray) { memberAttributes = mi.GetCustomAttributes(); } } else { valueType = null; } } object value = ReadValue(valueType, memberAttributes); if (valueType != null) { tableContent.Add(key, value); } SkipSpacesAndComment(); r = _dataReader.Peek(); if (r == ',') { _dataReader.Read(); } else if (r != '}') { throw new ParseException("Separation comma expected"); } } if (!isSuccess) { throw new ParseException($"Open bracket at {startPosition} is not closed"); } object result = null; if (tableType.IsArray) { bool skipNull = false; ArrayIndexMode indexMode = ArrayIndexMode.Default; LuaArrayAttribute arrayAttribute = null; if (attributes != null) { arrayAttribute = (LuaArrayAttribute)attributes.FirstOrDefault(x => x is LuaArrayAttribute); } if (arrayAttribute != null) { skipNull = arrayAttribute.SkipNull; indexMode = arrayAttribute.IndexMode; } int size = 0; if (skipNull) { size = tableContent.Keys.Count; } else if (tableContent.Keys.Count > 0) { foreach (int key in tableContent.Keys.Select(x => Convert.ToInt32(x))) { size = Math.Max(size, key); if (key == 0 && indexMode == ArrayIndexMode.Default) { indexMode = ArrayIndexMode.ZeroBased; } } if (indexMode == ArrayIndexMode.ZeroBased) { size++; } } Array array = Array.CreateInstance(valueType, size); int index = 0; foreach (object key in tableContent.Keys.OrderBy(x => Convert.ToInt32(x))) { int targetIndex = index; if (!skipNull) { targetIndex = Convert.ToInt32(key); if (indexMode != ArrayIndexMode.ZeroBased) { targetIndex--; } } if (targetIndex < 0) { throw new ParseException("Invalid Index"); } array.SetValue(tableContent[key], targetIndex); index++; } result = array; } else if (isTableTypeDict) { IDictionary dict = (IDictionary)Activator.CreateInstance(tableType); foreach (object key in tableContent.Keys) { dict.Add(key, tableContent[key]); } result = dict; } else if (typeof(IList).IsAssignableFrom(tableType)) { IList list = (IList)Activator.CreateInstance(tableType); foreach (object val in tableContent.Values) { list.Add(val); } result = list; } else if (genericTypeDefinition == typeof(IEnumerable <>)) { Type listType = typeof(List <>).MakeGenericType(new Type[] { valueType }); IList list = (IList)Activator.CreateInstance(listType); foreach (object val in tableContent.Values) { list.Add(val); } result = list; } else { object o = Activator.CreateInstance(tableType); foreach (object key in tableContent.Keys) { string keyString = key.ToString(); MemberInfo mi = memberNameInfoDict[keyString]; PropertyInfo pInfo = mi as PropertyInfo; FieldInfo fInfo = mi as FieldInfo; if (pInfo != null) { pInfo.SetValue(o, tableContent[key]); } else if (fInfo != null) { fInfo.SetValue(o, tableContent[key]); } } result = o; } return(result); }