예제 #1
0
        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);
        }
예제 #2
0
        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();
            }
        }