예제 #1
0
        private void ParseObject(object o, ObjectGraphContext context)
        {
            var type  = o.GetType();
            var props = ObjectGraphContext.GetKnownProperties(type);

            foreach (var p in props.Values)
            {
                var val = p.GetValue(o, new object[] { });
                ParseProperty(p.Name, o, val, context);
            }
        }
예제 #2
0
        private static void WriteObject(object o, TextWriter w, ObjectGraphContext context, int tabLevel)
        {
            // serialize object type and field count
            if (o is IDataObject)
            {
                // use data object code! :D
                var type = o.GetType();
                var data = (o as IDataObject).Data;
                w.WriteLine("p" + data.Count + ":");
                foreach (var kvp in data)
                {
                    var pname = kvp.Key;
                    var val   = kvp.Value;
                    var prop  = ObjectGraphContext.GetKnownProperties(type)[pname];
                    if (prop != null)
                    {
                        var ptype = prop.PropertyType;
                        WriteProperty(w, o, ptype, pname, val, context, tabLevel);
                    }
                    else
                    {
                        // TODO - if property doesn't exist, log a warning somewhere?
                        WriteProperty(w, o, typeof(object), pname, val, context, tabLevel);
                    }
                }
            }
            else
            {
                // use reflection :(
                var type  = o.GetType();
                var props = ObjectGraphContext.GetKnownProperties(type).Values.Where(p =>
                                                                                     p.HasAttribute <ForceSerializationWhenDefaultValueAttribute>() || // force serialization of property even if value is null/default?
                                                                                     !p.GetValue(o, null).SafeEquals(p.PropertyType.DefaultValue()));  // property value is not null/default?
                w.WriteLine("p" + props.Count() + ":");
                foreach (var p in props.OrderBy(p => GetSerializationPriority(p)))
                {
                    WriteProperty(w, o, p.PropertyType, p.Name, context.GetObjectProperty(o, p), context, tabLevel);
                }
            }

            // write end object
            for (int i = 0; i < tabLevel; i++)
            {
                w.Write('\t');
            }
            w.WriteLine(";");
        }
예제 #3
0
        private static void WriteCollection(IEnumerable list, TextWriter w, ObjectGraphContext context, int tabLevel)
        {
            var tabs = new string('\t', tabLevel);

            // collections get size and elements listed out
            Type itemType;
            var  type   = list.GetType();
            bool isDict = false;

            if (type.GetGenericArguments().Length == 2)
            {
                // HACK - assume it's a dictionary, no real way to test
                itemType = typeof(KeyValuePair <,>).MakeGenericType(type.GetGenericArguments());
                w.WriteLine("d" + list.Cast <object>().Count() + ":" + tabs);
                isDict = true;
            }
            else if (type.BaseType.GetGenericArguments().Length == 2)
            {
                // HACK - Resources inherits from a dictionary type
                itemType = typeof(KeyValuePair <,>).MakeGenericType(type.BaseType.GetGenericArguments());
                w.WriteLine("d" + list.Cast <object>().Count() + ":" + tabs);
                isDict = true;
            }
            else if (type == typeof(DynamicDictionary))
            {
                itemType = typeof(KeyValuePair <object, object>);
                w.WriteLine("d" + list.Cast <object>().Count() + ":" + tabs);
                isDict = true;
            }
            else if (type.GetGenericArguments().Length == 1)
            {
                // HACK - assume it's a collection, no real way to test
                itemType = type.GetGenericArguments()[0];
                w.WriteLine("c" + list.Cast <object>().Count() + ":" + tabs);
            }
            else
            {
                // no generic type? probably a list of objects?
                itemType = typeof(object);
                w.WriteLine("c" + list.Cast <object>().Count() + ":" + tabs);
            }
            foreach (var item in list)
            {
                if (isDict)
                {
                    var keyprop = ObjectGraphContext.GetKnownProperties(itemType)["Key"];
                    var valprop = ObjectGraphContext.GetKnownProperties(itemType)["Value"];
                    Serialize(context.GetObjectProperty(item, keyprop), w, keyprop.PropertyType, context, tabLevel + 1);
                    Serialize(context.GetObjectProperty(item, valprop), w, valprop.PropertyType, context, tabLevel + 1);
                }
                else
                {
                    Serialize(item, w, itemType, context, tabLevel + 1);
                }
            }

            // write end object
            for (int i = 0; i < tabLevel; i++)
            {
                w.Write('\t');
            }
            w.WriteLine(";");
        }
예제 #4
0
        private static object DeserializeObjectWithProperties(TextReader r, Type type, ObjectGraphContext context, StringBuilder log)
        {
            // create object and add it to our context
            var o = type.Instantiate();

            context.Add(o);

            // properties count - need to create object and populate properties
            int    count;
            string s = r.ReadTo(':', log);

            if (!int.TryParse(s, out count))
            {
                throw new SerializationException("Expected integer, got \"" + s + "\" when parsing property count.");
            }


            var dict = new SafeDictionary <string, object>();

            // deserialize the properties
            var props = ObjectGraphContext.GetKnownProperties(type, true);

            for (int i = 0; i < count; i++)
            {
                var pname = r.ReadTo(':', log).Trim();
                if (type == typeof(Game.Objects.Civilization.Empire) && pname == "StoredResources")
                {
                }
                if (props.ContainsKey(pname))
                {
                    // TODO - get base class recursively, not just derived class and declaring type
                    var prop = type.GetProperty(pname, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) ?? props[pname];                     // get concrete type property in case it has DoNotSerialize and the abstract type doesn't
                    if (prop != null)
                    {
                        if (prop.Name == "StarSystemNames")
                        {
                        }
                        var data = Deserialize(r, prop.PropertyType, false, context, log);
                        if (prop.HasAttribute <SerializationPriorityAttribute>())
                        {
                            prop.SetValue(o, data);                             // TODO - use cached reflection lambdas
                        }
                        if (!prop.HasAttribute <DoNotSerializeAttribute>())
                        {
                            dict[pname] = data;
                        }
                    }
                    else
                    {
                        r.ReadToEndOfLine(';', log);                         // throw away this property, we don't need it
                    }
                    // if p is null or has do not serialize attribute, it must be data from an old version with different property names, so don't crash
                }
            }

            //propertySetterTasks.Add(Task.Factory.StartNew(() =>
            //{
            o.SetData(dict, context);
            //}));

            // clean up
            ReadSemicolon(r, type, log);

            return(o);
        }
예제 #5
0
        private static IEnumerable DeserializeDictionary(TextReader r, Type type, ObjectGraphContext context, StringBuilder log)
        {
            IEnumerable o;
            int         size;
            var         sizeStr = r.ReadTo(':', log);

            if (!int.TryParse(sizeStr, out size))
            {
                throw new SerializationException("Expected integer, got \"" + sizeStr + "\" when parsing collection size.");
            }
            var coll = type.Instantiate();

            context.Add(coll);
            var  adder = type.GetMethods().Single(m => m.Name == "Add" && m.GetParameters().Length == 2);
            Type itemType;

            if (type.GetGenericArguments().Count() == 2)
            {
                itemType = typeof(KeyValuePair <,>).MakeGenericType(type.GetGenericArguments());
            }
            else if (type == typeof(DynamicDictionary))
            {
                itemType = typeof(KeyValuePair <object, object>);
            }
            else
            {
                // HACK - Resources inherits from a dictionary type
                itemType = typeof(KeyValuePair <,>).MakeGenericType(type.BaseType.GetGenericArguments());
            }

            var      collParm = Expression.Parameter(typeof(object), "coll");
            var      keyParm  = Expression.Parameter(typeof(object), "key");
            var      valParm  = Expression.Parameter(typeof(object), "val");
            var      keyprop  = ObjectGraphContext.GetKnownProperties(itemType, true)["Key"];
            var      valprop  = ObjectGraphContext.GetKnownProperties(itemType, true)["Value"];
            Delegate lambdaAdder;

            if (ObjectGraphContext.CollectionAdders[type] == null)
            {
                // lambda has not been created yet, so create it
                ObjectGraphContext.CollectionAdders[type] =
                    Expression.Lambda(Expression.Call(
                                          Expression.Convert(collParm, type),
                                          adder,
                                          Expression.Convert(keyParm, keyprop.PropertyType),
                                          Expression.Convert(valParm, valprop.PropertyType)
                                          ), collParm, keyParm, valParm).Compile();
            }

            // get lambda
            lambdaAdder = ObjectGraphContext.CollectionAdders[type];

            // load items and add them
            for (int i = 0; i < size; i++)
            {
                var key = Deserialize(r, keyprop.PropertyType, false, context, log);
                var val = Deserialize(r, valprop.PropertyType, false, context, log);
                lambdaAdder.DynamicInvoke(coll, key, val);
            }

            o = (IEnumerable)coll;

            // clean up
            ReadSemicolon(r, type, log);

            return(o);
        }