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("}");
            }
        }
Exemple #2
0
        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);
        }