public static ISimpleDataObject Create(object o, ObjectGraphContext ctx = null) { if (o == null) return null; var t = o.GetType(); return new SimpleDataObject(o, ctx); }
internal static T Deserialize <T>(Stream s, ObjectGraphContext context = null) { var sr = new StreamReader(new BufferedStream(s)); var result = Deserialize <T>(sr, context); return(result); }
public static ISimpleDataObject Load(SafeDictionary<string, IData> simpleData, ObjectGraphContext ctx = null) { if (simpleData == null) return null; var t = new SafeType(simpleData["!type"].Value as string).Type; return new SimpleDataObject(simpleData, ctx); }
private static void Serialize <T>(T o, Stream s, ObjectGraphContext context = null, int tabLevel = 0) { var sw = new StreamWriter(new BufferedStream(s)); Serialize(o, sw, context); sw.Flush(); }
public string SerializeToString(object o) { var ctx = new ObjectGraphContext(); var kos = new List <object>(); var parser = new ObjectGraphParser(); if (o == null) { // do nothing } else if (o.GetType().IsScalar()) { kos.Add(DataScalar.Create(o)); } else { Action <object> Parser_StartObject = x => { if (!x.GetType().IsScalar()) { var dobj = SimpleDataObject.Create(x, ctx); kos.Add(dobj); } }; parser.StartObject += new ObjectGraphParser.ObjectDelegate(Parser_StartObject); parser.Parse(o); } foreach (var dobj in kos.OfType <ISimpleDataObject>()) { dobj.InitializeData(ctx); } return(JsonConvert.SerializeObject(kos)); }
private void ParseColor(Color c, ObjectGraphContext context) { // HACK - Mono's implmentation of Color is different from .NET's so we need to save just the ARGB values in a consistent format ParseProperty("A", c, c.A, context); ParseProperty("R", c, c.R, context); ParseProperty("G", c, c.G, context); ParseProperty("B", c, c.B, context); }
public static object Deserialize(Stream s, Type desiredType, ObjectGraphContext context = null, StringBuilder log = null) { var sr = new StreamReader(s); var result = Deserialize(sr, desiredType, true, context, log); sr.Close(); return(result); }
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); } }
internal static void Serialize <T>(T o, TextWriter w, ObjectGraphContext context = null, int tabLevel = 0) { if (o == null) { Serialize(o, w, typeof(T), context, tabLevel); } else { Serialize(o, w, o.GetType(), context, tabLevel); } }
private void ParseCollection(IEnumerable list, ObjectGraphContext context) { foreach (var item in list.Cast <object>().ToArray()) { context.propertyStack.Push("(Collection Item)"); if (Item != null) { Item(item); } context.ObjectQueue.Enqueue(item); context.propertyStack.Pop(); } }
private void ParseProperty(string propertyName, object o, object val, ObjectGraphContext context) { context.propertyStack.Push(propertyName); bool recurse = true; // if no event handler, assume we are parsing recursively (really adding subproperties to queue) if (Property != null) { recurse = Property(propertyName, o, val); } if (recurse) { context.ObjectQueue.Enqueue(val); } context.propertyStack.Pop(); }
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(";"); }
public SimpleDataObject(object o, ObjectGraphContext ctx = null) { Context = ctx ?? new ObjectGraphContext(); if (o != null) { Type = o.GetType(); if (Context.GetID(o) == null) ID = Context.Add(o); Data = o.GetData(ctx); } else { Type = null; Data = new SafeDictionary<string, object>(); ID = -1; } }
private static void WriteArray(Array array, TextWriter w, ObjectGraphContext context, int tabLevel) { var tabs = new string('\t', tabLevel); // arrays get size and elements listed out var bounds = new List <string>(); for (var rank = 0; rank < array.Rank; rank++) { bounds.Add(array.GetLowerBound(rank) + "_" + array.GetUpperBound(rank)); } w.WriteLine("a" + string.Join(",", bounds.ToArray()) + ":" + tabs); var type = array.GetType(); var itemtype = type.GetElementType(); if (array.Rank == 1) { foreach (var item in array) { Serialize(item, w, itemtype, context, tabLevel + 1); } } else if (array.Rank == 2) { for (int x = array.GetLowerBound(0); x <= array.GetUpperBound(0); x++) { for (int y = array.GetLowerBound(1); y <= array.GetUpperBound(1); y++) { Serialize(array.GetValue(x, y), w, itemtype, context, tabLevel + 1); } } } else { throw new SerializationException("Arrays with more than 2 dimensions are not supported."); } // write end object for (int i = 0; i < tabLevel; i++) { w.Write('\t'); } w.WriteLine(";"); }
private static object DeserializeObjectWithID(TextReader r, Type type, ObjectGraphContext context, StringBuilder log) { // ID - need to find known object int id; string s = r.ReadToEndOfLine(';', log); if (!int.TryParse(s, out id)) { throw new SerializationException("Expected integer, got \"" + s + "\" when parsing object ID."); } // do we have it? if (!context.KnownObjects.ContainsKey(type) || context.KnownObjects[type].Count <= id) { throw new SerializationException("No known object of type " + type + " has an ID of " + id + "."); } // found it! return(context.KnownObjects[type][id]); }
private static object DeserializeObject(TextReader r, Type type, ObjectGraphContext context, StringBuilder log) { // read property count or id number object o; var fin = r.Read(); while (fin != 0 && char.IsWhiteSpace((char)fin)) { if (log != null) { log.Append((char)fin); } fin = r.Read(); } if (fin != 0 && log != null) { log.Append((char)fin); } if (fin == 'p') { o = DeserializeObjectWithProperties(r, type, context, log); } else if (fin == 'i') { o = DeserializeObjectWithID(r, type, context, log); } else if (fin == 'n') { // null object! o = null; // clean up ReadSemicolon(r, type, log); } else { throw new SerializationException("Expected 'p'/'i'/'n', got '" + (char)fin + "' when parsing " + type + "."); } return(o); }
private void ParseArray(Array array, ObjectGraphContext context) { if (ArrayDimensions != null) { var bounds = new List <int>(); for (var rank = 0; rank < array.Rank; rank++) { bounds.Add(array.GetLength(rank)); } ArrayDimensions(bounds); } foreach (var item in array) { context.propertyStack.Push("(Array Item)"); if (Item != null) { Item(item); } context.ObjectQueue.Enqueue(item); context.propertyStack.Pop(); } }
private static string DeserializeString(TextReader r, ObjectGraphContext context, StringBuilder log) { string o; bool foundRealSemicolon = false; StringBuilder sb = new StringBuilder(); int quotes = 0; while (!foundRealSemicolon) { var ns = r.ReadToEndOfLine(';', log); quotes += ns.Count(c => c == '"'); // TODO - don't count escaped quotes sb.Append(ns); if (!ns.EndsWith("\\") && quotes % 2 == 0) { foundRealSemicolon = true; } } var s = sb.ToString(); if (s == "n") { o = null; } else { o = s.Trim(); if (o.StartsWith("\"")) { o = o.Substring(1); } if (o.EndsWith("\"")) { o = o.Substring(0, o.Length - 1); } o = o.Replace("\\\"", "\"").Replace("\\;", ";").Replace("\\\\", "\\"); } return(o); }
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); }
public SimpleDataObject(SafeDictionary<string, IData> simpleData, ObjectGraphContext ctx = null) { SimpleData = simpleData; Context = ctx ?? new ObjectGraphContext(); }
public SimpleDataObject() { Context = new ObjectGraphContext(); Type = typeof(object); }
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 DeserializeStringifiedObject(TextReader r, Type type, ObjectGraphContext context, StringBuilder log) { object o; // read tag to see if it's actually a stringified object var fin = r.Read(); while (fin != 0 && char.IsWhiteSpace((char)fin)) { if (log != null) { log.Append((char)fin); } fin = r.Read(); } if (fin != 0 && log != null) { log.Append((char)fin); } if (fin == 's') { IStringifier stringifier = null; var t = type; while (stringifier == null && t != null) { stringifier = StringifierLibrary.Instance.All.SingleOrDefault(x => x.SupportedType == t); t = t.BaseType; } if (stringifier == null) { throw new Exception("Can't find stringifier to deserialize " + type); } var dummy = r.ReadTo(':', log); var val = r.ReadToEndOfLine(';', log); o = stringifier.Destringify(val); } else if (fin == 'p') { o = DeserializeObjectWithProperties(r, type, context, log); } else if (fin == 'i') { o = DeserializeObjectWithID(r, type, context, log); } else if (fin == 'n') { // null object! o = null; // clean up ReadSemicolon(r, type, log); } else if (fin == 'd') { o = DeserializeDictionary(r, type, context, log); } else if (fin == 'c') { o = DeserializeList(r, type, context, log); } else { throw new Exception("Unknown data tag " + fin + ", was expecting s/p/i/n/d/c."); } if (!context.KnownObjects.ContainsKey(type) || !context.KnownObjects[type].Contains(o)) { context.Add(o); } return(o); }
public void InitializeData(ObjectGraphContext ctx = null) { Data = Value.GetData(ctx ?? Context); }
public DataReference(ObjectGraphContext ctx, T t = default(T)) { Context = ctx; Value = t; }
public DataReference() { Context = new ObjectGraphContext(); }
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); }
public void InitializeValue(ObjectGraphContext ctx = null) { if (Context.GetID(Value) == null) Context.Add(Value); Value.SetData(Data, ctx ?? Context); }
public DataReference(ObjectGraphContext ctx, int id = -1) { Context = ctx; ID = id; }
public T Reconstitute<T>(ObjectGraphContext ctx = null) { var result = (T)typeof(T).Instantiate(); result.SetData(Data, ctx ?? new ObjectGraphContext()); return result; }