public IDictionary <Type, IList <object> > Parse(object o, ObjectGraphContext context = null) { // set up our context if we haven't already if (context == null) { context = new ObjectGraphContext(); } // fire up the queue context.ObjectQueue.Enqueue(o); while (context.ObjectQueue.Any()) { o = context.ObjectQueue.Dequeue(); context.objectStack.Push(o); // deal with nulls if (o == null) { if (Null != null) { Null(null); } context.objectStack.Pop(); continue; } var type = o.GetType(); int?id = null; if (!type.IsValueType && type != typeof(string)) { id = context.GetID(o); } if (!ObjectGraphContext.KnownTypes.ContainsKey(type.AssemblyQualifiedName)) { // register type ObjectGraphContext.KnownTypes.Add(type.AssemblyQualifiedName, type); ObjectGraphContext.AddProperties(type); } if (!type.IsValueType && type != typeof(string) && !typeof(Array).IsAssignableFrom(type)) { if (id == null) { // add to context context.Add(o); } else { if (KnownObject != null) { KnownObject(o); } // done context.objectStack.Pop(); continue; } } // object was found if (StartObject != null) { StartObject(o); } // parse sub objects if (type.IsPrimitive || typeof(Enum).IsAssignableFrom(type) || type == typeof(string)) { // nothing to do, no sub objects } else if (type == typeof(Color)) { ParseColor((Color)o, context); } else if (typeof(Array).IsAssignableFrom(type)) { ParseArray((Array)o, context); } else if (typeof(IEnumerable).IsAssignableFrom(type) && type.GetMethods().Where(m => m.Name == "Add" && m.GetParameters().Length == 1 || m.GetParameters().Length == 2).Any()) { ParseCollection((IEnumerable)o, context); } else { ParseObject(o, context); } // done parsing object if (EndObject != null) { EndObject(o); } context.objectStack.Pop(); } return(context.KnownObjects); }
internal static void Serialize(object o, TextWriter w, Type desiredType, ObjectGraphContext context = null, int tabLevel = 0) { var tabs = new string('\t', tabLevel); // type checking! if (o is Type) { throw new SerializationException("Cannot serialize objects of type System.Type."); } if (o != null && !desiredType.IsAssignableFrom(o.GetType())) { throw new SerializationException("Attempting to serialize " + o.GetType() + " as " + desiredType + "."); } // set up our serialization context if we haven't already if (context == null) { context = new ObjectGraphContext(); } // write some tabs to improve readability for (int i = 0; i < tabLevel; i++) { w.Write('\t'); } // deal with nulls if (o == null) { if (!ObjectGraphContext.KnownTypes.ContainsKey(GetShortTypeName(desiredType))) { ObjectGraphContext.KnownTypes.Add(GetShortTypeName(desiredType), desiredType); ObjectGraphContext.AddProperties(desiredType); } w.Write(GetShortTypeName(desiredType)); w.WriteLine(":n;"); return; } var type = o.GetType(); int?id = null; if (!type.IsValueType && type != typeof(string) && !(StringifierLibrary.Instance.All?.Any(x => x.SupportedType == type) ?? false)) { id = context.GetID(o); } if (!ObjectGraphContext.KnownTypes.ContainsKey(GetShortTypeName(type))) { // register type ObjectGraphContext.KnownTypes.Add(GetShortTypeName(type), type); ObjectGraphContext.AddProperties(type); } // write the type name if it's not the same as the desired type if (type == desiredType) { w.Write(":"); } else { w.WriteLine(GetShortTypeName(type) + ":"); } if (id == null && !type.IsValueType && type != typeof(string) && !typeof(Array).IsAssignableFrom(type)) { // add to context context.Add(o); } // deal with refs if (id != null) { // already seen this object, just write an ID if (type != desiredType) { w.Write(tabs); } w.Write("i"); w.Write(id); // write end object w.WriteLine(";"); // done return; } // write some tabs if (type != desiredType) { w.Write(tabs); } // serialize the object if (StringifierLibrary.Instance.All?.Any(x => x.SupportedType.IsAssignableFrom(type)) ?? false) { WriteStringifiedObject(o, w); } else if (type.IsPrimitive || typeof(Enum).IsAssignableFrom(type) || type.Name == "Nullable`1" || type == typeof(decimal)) { WritePrimitiveOrEnum(o, w); } else if (type == typeof(string)) { WriteString((string)o, w); } else if (type == typeof(Color)) { WriteColor((Color)o, w, tabLevel); } else if (typeof(Array).IsAssignableFrom(type)) { WriteArray((Array)o, w, context, tabLevel); } else if (typeof(IEnumerable).IsAssignableFrom(type) && type.GetMethods().Where(m => m.Name == "Add" && m.GetParameters().Length == 1 || m.GetParameters().Length == 2).Any() // these types should not be serialized as normal dictionaries/sets! && !typeof(IReferenceEnumerable).IsAssignableFrom(type)) { WriteCollection((IEnumerable)o, w, context, tabLevel); } else { WriteObject(o, w, context, tabLevel); } // flush the stream if we're all done if (tabLevel == 0) { w.Flush(); } }