public override object Read(Reader reader, int tag) { if (tag >= '0' && tag <= '9') { return(digitObject[tag - '0']); } var stream = reader.Stream; switch (tag) { case TagInteger: return(ValueReader.ReadInt(stream)); case TagString: return(ReferenceReader.ReadString(reader)); case TagBytes: return(ReferenceReader.ReadBytes(reader)); case TagTrue: return(trueObject); case TagFalse: return(falseObject); case TagEmpty: return(""); case TagObject: return(Read(reader)); case TagRef: return(reader.ReadReference()); case TagDate: return(ReferenceReader.ReadDateTime(reader)); case TagTime: return(ReferenceReader.ReadTime(reader)); case TagGuid: return(ReferenceReader.ReadGuid(reader)); case TagLong: switch (reader.LongType) { case LongType.Int64: return(ValueReader.ReadLong(stream)); case LongType.UInt64: return((ulong)ValueReader.ReadLong(stream)); default: return(ValueReader.ReadBigInteger(stream)); } case TagDouble: switch (reader.RealType) { case RealType.Single: return(ValueReader.ReadSingle(stream)); case RealType.Decimal: return(ValueReader.ReadDecimal(stream)); default: return(ValueReader.ReadDouble(stream)); } case TagNaN: switch (reader.RealType) { case RealType.Single: return(float.NaN); default: return(double.NaN); } case TagInfinity: switch (reader.RealType) { case RealType.Single: return(ValueReader.ReadSingleInfinity(stream)); default: return(ValueReader.ReadInfinity(stream)); } case TagUTF8Char: switch (reader.CharType) { case CharType.Char: return(ValueReader.ReadChar(stream)); default: return(ValueReader.ReadUTF8Char(stream)); } case TagList: switch (reader.ListType) { case ListType.Array: return(ReferenceReader.ReadArray <object>(reader)); case ListType.ArrayList: return(ListDeserializer <ArrayList> .Read(reader)); default: return(CollectionDeserializer <List <object>, object> .Read(reader)); } case TagMap: switch (reader.DictType) { case DictType.Dictionary: return(DictionaryDeserializer <Dictionary <object, object>, object, object> .Read(reader)); case DictType.ExpandoObject: return(ExpandoObjectDeserializer.Read(reader)); case DictType.Hashtable: return(DictionaryDeserializer <Hashtable> .Read(reader)); default: return(DictionaryDeserializer <NullableKeyDictionary <object, object>, object, object> .Read(reader)); } case TagError: return(new Exception(reader.Deserialize <string>())); default: return(base.Read(reader, tag)); } }
private static object DeserializeInternal(string name, Type type, object defaultvalue, IniDictionary ini, string groupName, bool rootObject, IniCollectionSettings collectionSettings) { string fullname = groupName; if (!rootObject) { if (!string.IsNullOrEmpty(fullname)) { fullname += '.'; } fullname += name; } if (!ini.ContainsKey(groupName)) { return(defaultvalue); } Dictionary <string, string> group = ini[groupName]; if (!type.IsComplexType()) { if (group.ContainsKey(name)) { object converted = type.ConvertFromString(group[name]); group.Remove(name); if (converted != null) { return(converted); } } return(defaultvalue); } Type generictype; if (type.IsArray) { Type valuetype = type.GetElementType(); int maxind = int.MinValue; if (!IsComplexType(valuetype)) { switch (collectionSettings.Mode) { case IniCollectionMode.Normal: foreach (IniNameValue item in group) { if (item.Key.StartsWith(name + "[", StringComparison.Ordinal)) { int key = int.Parse(item.Key.Substring(name.Length + 1, item.Key.Length - (name.Length + 2))); maxind = Math.Max(key, maxind); } } break; case IniCollectionMode.IndexOnly: foreach (IniNameValue item in group) { int key; if (int.TryParse(item.Key, out key)) { maxind = Math.Max(key, maxind); } } break; case IniCollectionMode.NoSquareBrackets: foreach (IniNameValue item in group) { if (item.Key.StartsWith(name, StringComparison.Ordinal)) { int key; if (int.TryParse(item.Key.Substring(name.Length), out key)) { maxind = Math.Max(key, maxind); } } } break; case IniCollectionMode.SingleLine: string[] items = group[name].Split(new[] { collectionSettings.Format }, StringSplitOptions.None); Array _obj = Array.CreateInstance(valuetype, items.Length); for (int i = 0; i < items.Length; i++) { _obj.SetValue(valuetype.ConvertFromString(items[i]), i); } group.Remove(name); break; } } else { switch (collectionSettings.Mode) { case IniCollectionMode.Normal: foreach (IniNameGroup item in ini) { if (item.Key.StartsWith(fullname + "[", StringComparison.Ordinal)) { int key = int.Parse(item.Key.Substring(fullname.Length + 1, item.Key.Length - (fullname.Length + 2))); maxind = Math.Max(key, maxind); } } break; case IniCollectionMode.IndexOnly: foreach (IniNameGroup item in ini) { int key; if (int.TryParse(item.Key, out key)) { maxind = Math.Max(key, maxind); } } break; case IniCollectionMode.NoSquareBrackets: foreach (IniNameGroup item in ini) { if (item.Key.StartsWith(fullname, StringComparison.Ordinal)) { int key = int.Parse(item.Key.Substring(fullname.Length)); maxind = Math.Max(key, maxind); } } break; case IniCollectionMode.SingleLine: throw new InvalidOperationException("Cannot deserialize type " + valuetype + " with IniCollectionMode.SingleLine!"); } } if (maxind == int.MinValue) { return(Array.CreateInstance(valuetype, 0)); } int length = maxind + 1 - (collectionSettings.Mode == IniCollectionMode.SingleLine ? 0 : collectionSettings.StartIndex); Array obj = Array.CreateInstance(valuetype, length); if (!IsComplexType(valuetype)) { switch (collectionSettings.Mode) { case IniCollectionMode.Normal: for (int i = 0; i < length; i++) { if (group.ContainsKey(name + "[" + (i + collectionSettings.StartIndex).ToString() + "]")) { obj.SetValue(valuetype.ConvertFromString(group[name + "[" + (i + collectionSettings.StartIndex).ToString() + "]"]), i); group.Remove(name + "[" + (i + collectionSettings.StartIndex).ToString() + "]"); } else { obj.SetValue(valuetype.GetDefaultValue(), i); } } break; case IniCollectionMode.IndexOnly: for (int i = 0; i < length; i++) { if (group.ContainsKey((i + collectionSettings.StartIndex).ToString())) { obj.SetValue(valuetype.ConvertFromString(group[(i + collectionSettings.StartIndex).ToString()]), i); group.Remove((i + collectionSettings.StartIndex).ToString()); } else { obj.SetValue(valuetype.GetDefaultValue(), i); } } break; case IniCollectionMode.NoSquareBrackets: for (int i = 0; i < length; i++) { if (group.ContainsKey(name + (i + collectionSettings.StartIndex).ToString())) { obj.SetValue(valuetype.ConvertFromString(group[name + (i + collectionSettings.StartIndex).ToString()]), i); group.Remove(name + (i + collectionSettings.StartIndex).ToString()); } else { obj.SetValue(valuetype.GetDefaultValue(), i); } } break; } } else { switch (collectionSettings.Mode) { case IniCollectionMode.Normal: for (int i = 0; i < length; i++) { obj.SetValue(DeserializeInternal("value", valuetype, valuetype.GetDefaultValue(), ini, fullname + "[" + (i + collectionSettings.StartIndex).ToString() + "]", true, defaultCollectionSettings), i); } break; case IniCollectionMode.IndexOnly: for (int i = 0; i < length; i++) { obj.SetValue(DeserializeInternal("value", valuetype, valuetype.GetDefaultValue(), ini, (i + collectionSettings.StartIndex).ToString(), true, defaultCollectionSettings), i); } break; case IniCollectionMode.NoSquareBrackets: for (int i = 0; i < length; i++) { obj.SetValue(DeserializeInternal("value", valuetype, valuetype.GetDefaultValue(), ini, fullname + (i + collectionSettings.StartIndex).ToString(), true, defaultCollectionSettings), i); } break; } } return(obj); } if (ImplementsGenericDefinition(type, typeof(IList <>), out generictype)) { object obj = Activator.CreateInstance(type); Type valuetype = generictype.GetGenericArguments()[0]; CollectionDeserializer deserializer = (CollectionDeserializer)Activator.CreateInstance(typeof(ListDeserializer <>).MakeGenericType(valuetype)); deserializer.Deserialize(obj, group, groupName, collectionSettings, name, ini, fullname); return(obj); } if (type.ImplementsGenericDefinition(typeof(IDictionary <,>), out generictype)) { object obj = Activator.CreateInstance(type); Type keytype = generictype.GetGenericArguments()[0]; Type valuetype = generictype.GetGenericArguments()[1]; if (keytype.IsComplexType()) { return(obj); } CollectionDeserializer deserializer = (CollectionDeserializer)Activator.CreateInstance(typeof(DictionaryDeserializer <,>).MakeGenericType(keytype, valuetype)); deserializer.Deserialize(obj, group, groupName, collectionSettings, name, ini, fullname); return(obj); } object result = Activator.CreateInstance(type); MemberInfo collection = null; foreach (MemberInfo member in type.GetMembers(BindingFlags.Public | BindingFlags.Instance)) { if (Attribute.GetCustomAttribute(member, typeof(IniIgnoreAttribute), true) != null) { continue; } string membername = member.Name; if (Attribute.GetCustomAttribute(member, typeof(IniNameAttribute), true) != null) { membername = ((IniNameAttribute)Attribute.GetCustomAttribute(member, typeof(IniNameAttribute), true)).Name; } IniCollectionSettings colset = defaultCollectionSettings; IniCollectionAttribute colattr = (IniCollectionAttribute)Attribute.GetCustomAttribute(member, typeof(IniCollectionAttribute), true); if (colattr != null) { colset = colattr.Settings; } switch (member.MemberType) { case MemberTypes.Field: FieldInfo field = (FieldInfo)member; if (colset.Mode == IniCollectionMode.IndexOnly && typeof(ICollection).IsAssignableFrom(field.FieldType)) { if (collection != null) { throw new Exception("IniCollectionMode.IndexOnly cannot be used on multiple members of a Type."); } collection = member; continue; } object defval = field.FieldType.GetDefaultValue(); DefaultValueAttribute defattr = (DefaultValueAttribute)Attribute.GetCustomAttribute(member, typeof(DefaultValueAttribute), true); if (defattr != null) { defval = defattr.Value; } field.SetValue(result, DeserializeInternal(membername, field.FieldType, defval, ini, fullname, false, colset)); break; case MemberTypes.Property: PropertyInfo property = (PropertyInfo)member; if (property.GetIndexParameters().Length > 0) { continue; } if (colset.Mode == IniCollectionMode.IndexOnly && typeof(ICollection).IsAssignableFrom(property.PropertyType)) { if (collection != null) { throw new Exception("IniCollectionMode.IndexOnly cannot be used on multiple members of a Type."); } collection = member; continue; } defval = property.PropertyType.GetDefaultValue(); defattr = (DefaultValueAttribute)Attribute.GetCustomAttribute(member, typeof(DefaultValueAttribute), true); if (defattr != null) { defval = defattr.Value; } object propval = DeserializeInternal(membername, property.PropertyType, defval, ini, fullname, false, colset); MethodInfo setmethod = property.GetSetMethod(); if (setmethod == null) { continue; } setmethod.Invoke(result, new object[] { propval }); break; } } if (collection != null) { switch (collection.MemberType) { case MemberTypes.Field: FieldInfo field = (FieldInfo)collection; field.SetValue(result, DeserializeInternal(collection.Name, field.FieldType, field.FieldType.GetDefaultValue(), ini, fullname, false, ((IniCollectionAttribute)Attribute.GetCustomAttribute(collection, typeof(IniCollectionAttribute), true)).Settings)); break; case MemberTypes.Property: PropertyInfo property = (PropertyInfo)collection; object propval = DeserializeInternal(collection.Name, property.PropertyType, property.PropertyType.GetDefaultValue(), ini, fullname, false, ((IniCollectionAttribute)Attribute.GetCustomAttribute(collection, typeof(IniCollectionAttribute), true)).Settings); MethodInfo setmethod = property.GetSetMethod(); if (setmethod == null) { break; } setmethod.Invoke(result, new object[] { propval }); break; } } ini.Remove(rootObject ? string.Empty : name); return(result); }
private static object DeserializeInternal(string name, Type type, object defaultvalue, Dictionary <string, Dictionary <string, string> > ini, string groupName, bool rootObject, bool usecollectionname) { string fullname = groupName; if (!rootObject) { if (!string.IsNullOrEmpty(fullname)) { fullname += '.'; } fullname += name; } if (!ini.ContainsKey(groupName)) { return(defaultvalue); } Dictionary <string, string> group = ini[groupName]; if (!type.IsComplexType()) { if (group.ContainsKey(name)) { object converted = type.ConvertFromString(group[name]); group.Remove(name); if (converted != null) { return(converted); } } return(defaultvalue); } if (type.IsArray) { Type valuetype = type.GetElementType(); int maxind = -1; if (!IsComplexType(valuetype)) { foreach (KeyValuePair <string, string> item in group) { if (!usecollectionname) { if (int.TryParse(item.Key, out int key)) { maxind = Math.Max(key, maxind); } } else if (item.Key.StartsWith(name + "[")) { int key = int.Parse(item.Key.Substring(name.Length + 1, item.Key.Length - (name.Length + 2))); maxind = Math.Max(key, maxind); } } } else { foreach (KeyValuePair <string, Dictionary <string, string> > item in ini) { if (!usecollectionname) { if (int.TryParse(item.Key, out int key)) { maxind = Math.Max(key, maxind); } } else if (item.Key.StartsWith(fullname + "[")) { int key = int.Parse(item.Key.Substring(fullname.Length + 1, item.Key.Length - (fullname.Length + 2))); maxind = Math.Max(key, maxind); } } } maxind++; Array obj = Array.CreateInstance(valuetype, maxind); if (!IsComplexType(valuetype)) { for (int i = 0; i < maxind; i++) { if (group.ContainsKey(usecollectionname ? name + "[" + i + "]" : i.ToString())) { obj.SetValue(ConvertFromString(valuetype, group[usecollectionname ? name + "[" + i + "]" : i.ToString()]), i); group.Remove(usecollectionname ? name + "[" + i + "]" : i.ToString()); } else { obj.SetValue(valuetype.GetDefaultValue(), i); } } } else { for (int i = 0; i < maxind; i++) { obj.SetValue(DeserializeInternal("value", valuetype, valuetype.GetDefaultValue(), ini, usecollectionname ? fullname + "[" + i + "]" : i.ToString(), true, true), i); } } return(obj); } if (ImplementsGenericDefinition(type, typeof(IList <>), out Type generictype)) { object obj = Activator.CreateInstance(type); Type valuetype = generictype.GetGenericArguments()[0]; CollectionDeserializer deserializer = (CollectionDeserializer)Activator.CreateInstance(typeof(ListDeserializer <>).MakeGenericType(valuetype)); deserializer.Deserialize(obj, group, groupName, usecollectionname, name, ini, fullname); return(obj); } if (type.ImplementsGenericDefinition(typeof(IDictionary <,>), out generictype)) { object obj = Activator.CreateInstance(type); Type keytype = generictype.GetGenericArguments()[0]; Type valuetype = generictype.GetGenericArguments()[1]; if (keytype.IsComplexType()) { return(obj); } CollectionDeserializer deserializer = (CollectionDeserializer)Activator.CreateInstance(typeof(DictionaryDeserializer <,>).MakeGenericType(keytype, valuetype)); deserializer.Deserialize(obj, group, groupName, usecollectionname, name, ini, fullname); return(obj); } object result = Activator.CreateInstance(type); MemberInfo collection = null; foreach (MemberInfo member in type.GetMembers(BindingFlags.Public | BindingFlags.Instance)) { if (Attribute.GetCustomAttribute(member, typeof(IniIgnoreAttribute), true) != null) { continue; } string membername = member.Name; if (Attribute.GetCustomAttribute(member, typeof(IniNameAttribute), true) != null) { membername = ((IniNameAttribute)Attribute.GetCustomAttribute(member, typeof(IniNameAttribute), true)).Name; } bool collectionattr = Attribute.GetCustomAttribute(member, typeof(IniCollectionAttribute), true) != null; switch (member.MemberType) { case MemberTypes.Field: FieldInfo field = (FieldInfo)member; if (collectionattr && typeof(ICollection).IsAssignableFrom(field.FieldType)) { if (collection != null) { throw new Exception("IniCollectionAttribute cannot be used on multiple members of a Type."); } collection = member; continue; } object defval = field.FieldType.GetDefaultValue(); DefaultValueAttribute defattr = (DefaultValueAttribute)Attribute.GetCustomAttribute(member, typeof(DefaultValueAttribute), true); if (defattr != null) { defval = defattr.Value; } field.SetValue(result, DeserializeInternal(membername, field.FieldType, defval, ini, fullname, false, true)); break; case MemberTypes.Property: PropertyInfo property = (PropertyInfo)member; if (property.GetIndexParameters().Length > 0) { continue; } if (collectionattr && typeof(ICollection).IsAssignableFrom(property.PropertyType)) { if (collection != null) { throw new Exception("IniCollectionAttribute cannot be used on multiple members of a Type."); } collection = member; continue; } defval = property.PropertyType.GetDefaultValue(); defattr = (DefaultValueAttribute)Attribute.GetCustomAttribute(member, typeof(DefaultValueAttribute), true); if (defattr != null) { defval = defattr.Value; } object propval = DeserializeInternal(membername, property.PropertyType, defval, ini, fullname, false, true); MethodInfo setmethod = property.GetSetMethod(); if (setmethod == null) { continue; } setmethod.Invoke(result, new object[] { propval }); break; } } if (collection != null) { switch (collection.MemberType) { case MemberTypes.Field: FieldInfo field = (FieldInfo)collection; field.SetValue(result, DeserializeInternal(collection.Name, field.FieldType, field.FieldType.GetDefaultValue(), ini, fullname, false, false)); break; case MemberTypes.Property: PropertyInfo property = (PropertyInfo)collection; object propval = DeserializeInternal(collection.Name, property.PropertyType, property.PropertyType.GetDefaultValue(), ini, fullname, false, false); MethodInfo setmethod = property.GetSetMethod(); if (setmethod == null) { break; } setmethod.Invoke(result, new object[] { propval }); break; } } ini.Remove(rootObject ? string.Empty : name); return(result); }