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); } }
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(";"); }
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(";"); }
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); }
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); }