object ReadObject(ReflectType ts, ulong oid, object possibleValue) { Func <object, object> RETURN_REGISTER = (value) => { // register everything, value types might have been written as objects! if (oid > 0) { Context.Register(oid, value); } return(value); }; switch (ts.Kind) { default: case PrimitiveType.Object: { if (ts.IsArray) { var ranks = Enumerable.Range(0, ts.ArrayRank).Select(x => (int)Reader.ReadVInt()).ToArray(); var array = Array.CreateInstance(ts.Element.Type ?? typeof(Missing), ranks); if (oid != 0) { Context.Register(oid, array); } if (ranks.All(x => x > 0)) { var indices = new int[ranks.Length]; do { var value = Read(ts.Element, null); array.SetValue(value, indices); }while (Inc(indices, ranks)); } return(array); } else if (ts.IsNullable) { object o = null; var isThere = Reader.ReadBool(); if (isThere) { o = Read(ts.GenericArguments[0], null); } if (oid != 0) { Context.Register(oid, o); } return(o); } else if (ts.IsEnum) { var eoVal = Read(ts.Element, null); var eVal = ts.Type != null?Enum.ToObject(ts.Type, eoVal) : eoVal; if (oid != 0) { Context.Register(oid, eVal); } return(eVal); } else { object o = null; if (ts.Type == null) { var missing = new Missing(ts); o = missing; if (oid != 0) { Context.Register(oid, missing); } foreach (var p in ts.Members) { var value = Read(p.Type, null); missing.Members[p.Name].Value = value; } var colt = ts.CollectionInterface; switch (colt.CollectionType) { case ReflectCollectionType.IList: case ReflectCollectionType.ICollectionT: { var list = new List <Tuple <object, object> >(); missing.Collection = list; var N = (int)Reader.ReadVInt(); var coll = colt.Collection1 ?? ReflectType.RObject; for (int i = 0; i < N; i++) { var value = Read(coll, null); list.Add(Tuple.Create <object, object>(value, null)); } } break; case ReflectCollectionType.IDictionary: case ReflectCollectionType.IDictionaryKV: { var list = new List <Tuple <object, object> >(); missing.Collection = list; var N = (int)Reader.ReadVInt(); var coll1 = colt.Collection1 ?? ReflectType.RObject; var coll2 = colt.Collection2 ?? ReflectType.RObject; for (int i = 0; i < N; i++) { var key = Read(coll1, null); var value = Read(coll2, null); list.Add(Tuple.Create <object, object>(key, value)); } } break; } return(o); } else { o = possibleValue ?? ts.FastType.TryConstruct(); if (oid != 0) { Context.Register(oid, o); } foreach (var m in ts.RuntimeMembers) { if (m.RuntimeMember == null || !m.RuntimeMember.TryFastReadSet(this.Reader, o)) { object org = null; if (m.Type.IsReference) { org = m.RuntimeMember?.GetValue(o); } var value = Read(m.Type, org); m.RuntimeMember?.SetValue(o, value); } } var colt = ts.CollectionInterface; switch (colt.CollectionType) { case ReflectCollectionType.IList: ReadList((IList)o); break; case ReflectCollectionType.IDictionary: ReadDict((IDictionary)o); break; case ReflectCollectionType.ICollectionT: if (colt.listRead == null) { colt.listRead = FastMethod.GetMethod(GetType().TryGetMethods("ReadCollectionT", new[] { colt.Collection1.Type }, ts.Type, typeof(ReflectType)).First()); } if (colt.listRead != null) { colt.listRead.Invoke(this, o, colt.Collection1); } break; case ReflectCollectionType.IDictionaryKV: if (colt.listRead == null) { colt.listRead = FastMethod.GetMethod(GetType().TryGetMethods("ReadDictKV", new[] { colt.Collection1.Type, colt.Collection2.Type }, ts.Type, typeof(ReflectType), typeof(ReflectType)).First()); } if (colt.listRead != null) { colt.listRead.Invoke(this, o, colt.Collection1, colt.Collection2); } break; } } return(o); } } case PrimitiveType.String: return(RETURN_REGISTER(this.Reader.ReadString())); case PrimitiveType.Bytes: return(RETURN_REGISTER(this.Reader.ReadBytes())); case PrimitiveType.Guid: return(RETURN_REGISTER(this.Reader.ReadGuid())); case PrimitiveType.Bool: return(RETURN_REGISTER(this.Reader.ReadBool())); case PrimitiveType.Char: return(RETURN_REGISTER(this.Reader.ReadChar())); case PrimitiveType.Byte: return(RETURN_REGISTER(this.Reader.ReadByte())); case PrimitiveType.SByte: return(RETURN_REGISTER(this.Reader.ReadSByte())); case PrimitiveType.Int16: return(RETURN_REGISTER(this.Reader.ReadInt16())); case PrimitiveType.UInt16: return(RETURN_REGISTER(this.Reader.ReadUInt16())); case PrimitiveType.Int32: return(RETURN_REGISTER(this.Reader.ReadInt32())); case PrimitiveType.UInt32: return(RETURN_REGISTER(this.Reader.ReadUInt32())); case PrimitiveType.Int64: return(RETURN_REGISTER(this.Reader.ReadInt64())); case PrimitiveType.UInt64: return(RETURN_REGISTER(this.Reader.ReadUInt64())); case PrimitiveType.Single: return(RETURN_REGISTER(this.Reader.ReadSingle())); case PrimitiveType.Double: return(RETURN_REGISTER(this.Reader.ReadDouble())); case PrimitiveType.Decimal: return(RETURN_REGISTER(this.Reader.ReadDecimal())); } }
object ReadISerializable(ReflectType ts, ulong oid, object possibleValue) { #if __PCL__ throw new PlatformNotSupportedException("PCL"); #elif __NETCORE__ var missing = new Missing(ts); var list = new List <Tuple <object, object> >(); missing.Collection = list; var N = Reader.ReadVInt(); for (int i = 0; i < N; i++) { var s = (string)Read(ReflectType.RString, null); var o = Read(ReflectType.RObject, null); list.Add(Tuple.Create <object, object>(s, o)); } if (ts.Type != null) { return(possibleValue); } return(missing); #else var info = new SRS.SerializationInfo(typeof(object), new SRS.FormatterConverter()); var ctx = new SRS.StreamingContext(SRS.StreamingContextStates.Persistence); var N = (int)Reader.ReadVInt(); for (int i = 0; i < N; i++) { var s = (string)Read(ReflectType.RString, null); var o = Read(ReflectType.RObject, null); info.AddValue(s, o); } if (ts.Type != null) { if (possibleValue != null && ts.Type.IsInstanceOf(possibleValue)) { var ctor = ts.Type.TryGetConstructors(info.GetType(), ctx.GetType()).FirstOrDefault(); // No FastMethod(): couldn't manage to call constructor on existing instance if (ctor != null) { ctor.Invoke(possibleValue, new object[] { info, ctx }); // Dare to do it! Call constructor on existing instance!! } if (oid > 0) { Context.Register(oid, possibleValue); } return(possibleValue); } var o = ts.Type.TryConstruct(info, ctx) ?? ts.FastType.TryConstruct(); if (oid > 0) { Context.Register(oid, o); } return(o); } var missing = new Missing(ts); if (oid > 0) { Context.Register(oid, missing); } var list = new List <Tuple <object, object> >(); missing.Collection = list; foreach (var kv in info) { list.Add(Tuple.Create <object, object>(kv.Name, kv.Value)); } return(missing); #endif }