static string Stringify(SerializedCollection instance, string indent, bool skipFirst) { var builder = new StringBuilder(); builder.AppendFormat("{0}{1}{2}", NameString(instance, indent, skipFirst), TypeString(instance), Environment.NewLine); builder.AppendLine(indent + "{"); foreach (var item in instance.Items) { if (item is SerializedAtom) { builder.AppendLine(Stringify(item as SerializedAtom, indent + " ")); } else { builder.Append(Stringify(item, indent + " ")); } } builder.AppendLine(indent + "}"); return(builder.ToString()); }
SerializedObject SerializeInternal(string name, object instance, Type declaredType) { SerializedObject child; var type = instance == null ? declaredType : instance.GetType(); // Atomic values if (instance == null || IsAtomic(type)) { child = new SerializedAtom { Name = name, Type = type, Value = instance }; } else if (IsXmlType(type)) { using (var sw = new StringWriter()) using (var xw = XmlWriter.Create(sw, new XmlWriterSettings { ConformanceLevel = ConformanceLevel.Fragment })) { if (xw == null) { throw new Exception("SerializeInternal error. xw is null"); } xw.WriteStartElement("root"); var xmlSerializable = instance as IXmlSerializable; if (xmlSerializable == null) { throw new Exception("SerializeInternal error. xmlSerializable is null"); } xmlSerializable.WriteXml(xw); xw.WriteEndElement(); xw.Flush(); sw.Flush(); child = new SerializedXml { Name = name, Type = type, Value = sw.ToString() }; } } else if (IsSerializable(type)) { using (var ms = new MemoryStream()) { serializer.Serialize(ms, instance); ms.Flush(); child = new SerializedXml() { Name = name, Type = type, Value = Encoding.Default.GetString(ms.ToArray()) }; } } // Dictionaries else if (type.IsGenericDictionary()) { var dictionary = instance as IDictionary; if (dictionary == null) { throw new Exception("SerializeInternal error. dictionary is null"); } var genericArguments = dictionary.GetType().GetGenericArguments(); var keyDeclaredType = genericArguments[0]; var valueDeclaredType = genericArguments[1]; child = new SerializedAggregate { Name = name }; var childAggregation = child as SerializedAggregate; foreach (var key in dictionary.Keys) { childAggregation.Children.Add( SerializeInternal(null, key, keyDeclaredType), SerializeInternal(null, dictionary[key], valueDeclaredType)); } } // Arrays, lists and sets (any collection excluding dictionaries) else if (type.IsGenericCollection()) { var collection = instance as IEnumerable; if (collection == null) { throw new Exception("SerializeInternal error. dictionary is null"); } var declaredItemType = type.IsArray ? type.GetElementType() : type.GetGenericArguments()[0]; child = new SerializedCollection { Name = name }; var childCollection = child as SerializedCollection; foreach (var item in collection) { childCollection.Items.Add(SerializeInternal(null, item, declaredItemType)); } } // Everything else (serialized with recursive property reflection) else { child = new SerializedAggregate { Name = name }; var childAggregation = child as SerializedAggregate; foreach (var memberInfo in _reflectionProvider.GetSerializableMembers(type)) { var memberAttr = _reflectionProvider.GetSingleAttributeOrDefault <SerializationAttribute>(memberInfo); // Make sure we want it serialized if (memberAttr.Ignore) { continue; } var memberType = memberInfo.GetMemberType(); object value = null; try { value = _reflectionProvider.GetValue(memberInfo, instance); } catch { } // Optional properties are skipped when serializing a default or null value if (!memberAttr.Required && (value == null || IsDefault(value, (memberInfo as PropertyInfo) != null ? (memberInfo as PropertyInfo).PropertyType : (memberInfo as FieldInfo).FieldType))) { continue; } // If no property name is defined, use the short type name var memberName = memberAttr.Name ?? memberInfo.Name; childAggregation.Children.Add(memberName, SerializeInternal(memberName, value, memberType)); } } // Write the runtime type if different (except nullables since they get unboxed) //if (!declaredType.IsNullable() && type != declaredType) child.Type = type.HasParameterlessConstructor() ? type : declaredType; return(child); }