/// <summary> /// Write a given object to stream /// </summary> /// <param name="obj">Object to write</param> /// <param name="ms">Stream to write to</param> public static void Serialize(object obj, SuperStream ms) { if (typeof(IStreamDataFinalizer).IsAssignableFrom(obj.GetType())) { IStreamDataFinalizer fin = (IStreamDataFinalizer)obj; fin.OnSerialize(); } var properties = StreamDataInfo.GetProperties(obj.GetType()); // Parse spell arguments foreach (var pi in properties) { dynamic value = pi.PropertyInfo.SafeGetValue(obj, null); StreamDataParserTask task = new StreamDataParserTask(ms, pi.ReadType, pi.DataType, pi.Attributes); if (pi.IsCollection) { // Find actual length of collection. ulong length; if (pi.IsArray) { length = (ulong)value.Length; } else if (pi.IsList) { length = (ulong)value.Count; } else { throw new Exception("Property is collection, but not array nor list."); } // Write length, and return written length. (Entries= will override length of collection if set) length = pi.WriteContentLength(ms, length); dynamic enumerable = pi.PropertyInfo.SafeGetValue(obj, null); ulong count = 0; foreach (var entry in enumerable) { // Make sure we do not write more entries than we've declared count++; if (count > length) { throw new Exception("Collection contains more items than "); } // Write enry. if (!WriteParserData(task, entry)) { throw new Exception(); } } continue; } else { if (!WriteParserData(task, value)) { throw new Exception(); } } } }
/// <summary> /// Populates an existing object with data from stream. /// </summary> /// <param name="obj"></param> /// <param name="ms"></param> /// <returns></returns> public static object Populate(object obj, SuperStream ms) { var properties = StreamDataInfo.GetProperties(obj.GetType()); bool gracefulStopAtEOF = obj.GetType().GetAttribute <StreamDataGracefulEofAttribute>() != null; dynamic value; // Parse spell arguments foreach (var pi in properties) { if (gracefulStopAtEOF && ms.EOF) { break; } StreamDataParserTask task = new StreamDataParserTask(ms, pi.ReadType, pi.DataType, pi.Attributes); if (pi.IsCollection) { var entries = pi.ReadContentLength(ms); if (pi.IsArray) { var arr = new ArrayList((int)Math.Min(int.MaxValue, entries)); for (ulong i = 0; i < entries; i++) { if (!GetParserData(task, out value)) { throw new Exception(); } arr.Add(value); } var arr2 = arr.ToArray(pi.ReadType); pi.PropertyInfo.SafeSetValue(obj, arr2, null); continue; } else if (pi.IsList) { dynamic list = Activator.CreateInstance( typeof(List <>).MakeGenericType(pi.DataType), (int)Math.Min(int.MaxValue, entries)); for (ulong i = 0; i < entries; i++) { if (!GetParserData(task, out value)) { throw new Exception(); } list.Add(value); } pi.PropertyInfo.SafeSetValue(obj, (object)list, null); } } else { if (!GetParserData(task, out value)) { throw new Exception(); } pi.PropertyInfo.SafeSetValue(obj, (object)value, null); continue; } } if (typeof(IStreamDataFinalizer).IsAssignableFrom(obj.GetType())) { IStreamDataFinalizer fin = (IStreamDataFinalizer)obj; fin.OnDeserialize(); } return(obj); }