private static void FillMethods(Type type, ReflectType newType, ReflectAssembly newassembly, ReflectNamespace currNamespace) { foreach (var methodInfo in type.GetMethods()) { // Finds or crates a new Type on this assembly Tuple <ReflectNamespace, ReflectAssembly> asmns = FindNamespaceAndAssembly(methodInfo.ReturnType); var newMethod = new ReflectMethod() { Name = methodInfo.Name, Parameters = new List <ReflectParameter>(), Return = AddNewSimpleReflectType(methodInfo.ReturnType, asmns.Item2, asmns.Item1) }; foreach (var parameterInfo in methodInfo.GetParameters()) { Tuple <ReflectNamespace, ReflectAssembly> asmns2 = FindNamespaceAndAssembly(parameterInfo.ParameterType); newMethod.Parameters.Add(new ReflectParameter() { Name = parameterInfo.Name, Type = AddNewSimpleReflectType(parameterInfo.ParameterType, asmns2.Item2, asmns2.Item1) }); } newType.Methods.Add(newMethod); } }
static ObjectContext() { WellKnownContext = new ObjectContext(); // 0 <==> null ulong index = 1; // essential type that must be shared by all serialized stream WellKnownContext.Register(index++, ReflectType.RObject); WellKnownContext.Register(index++, ReflectType.RString); WellKnownContext.Register(index++, ReflectType.RType); WellKnownContext.Register(index++, ReflectType.RReflectType); WellKnownContext.Register(index++, ReflectType.RNullable); // other well known values, to speed up read-write and reduce stream size WellKnownContext.Register(index++, ""); WellKnownContext.Register(index++, ReflectType.GetType(typeof(byte[]))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(Guid))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(bool))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(char))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(byte))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(sbyte))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(short))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(ushort))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(int))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(uint))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(long))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(ulong))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(float))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(double))); WellKnownContext.Register(index++, ReflectType.GetType(typeof(decimal))); }
private static void FillConstructors(Type type, ReflectType newType, ReflectAssembly newassembly, ReflectNamespace currNamespace) { foreach (var constructorInfo in type.GetConstructors()) { var newMethod = new ReflectMethod() { Name = constructorInfo.Name, Parameters = new List <ReflectParameter>(), Return = null }; foreach (var parameterInfo in constructorInfo.GetParameters()) { Tuple <ReflectNamespace, ReflectAssembly> asmns2 = FindNamespaceAndAssembly(parameterInfo.ParameterType); newMethod.Parameters.Add(new ReflectParameter() { Name = parameterInfo.Name, Type = AddNewSimpleReflectType(parameterInfo.ParameterType, asmns2.Item2, asmns2.Item1) }); } newType.Contructors.Add(newMethod); } }
void WriteISerializable(ReflectType ots, object o) { if (o is Missing) { var m = (Missing)o; Writer.WriteVInt(m.Collection.Count); foreach (var item in m.Collection) { Write(ReflectType.RString, (string)item.Item1); Write(ReflectType.RObject, item.Item2); } } else { #if __NETCORE__ throw new PlatformNotSupportedException(".NETCore + ISerializable"); #elif !__PCL__ var serial = (SRS.ISerializable)o; var info = new SRS.SerializationInfo(typeof(object), new SRS.FormatterConverter()); var ctx = new SRS.StreamingContext(SRS.StreamingContextStates.Persistence); serial.GetObjectData(info, ctx); Writer.WriteVInt(info.MemberCount); foreach (var item in info) { Write(ReflectType.RString, item.Name); Write(ReflectType.RObject, item.Value); } #endif } }
string ToTypeName(ReflectType type) { var sb = new StringBuilder(); ToTypeName(sb, type); return(sb.ToString()); }
object ReadConverter(ReflectType ts, ulong oid) { #if __PCL__ throw new PlatformNotSupportedException("PCL"); #else var s = (string)Read(ReflectType.RString, null); var tc = ts.GetTypeConverter(); if (tc != null) { var o = tc.ConvertFromInvariantString(s); if (oid > 0) { Context.Register(oid, o); } return(o); } var missing = new Missing(ts); if (oid > 0) { Context.Register(oid, missing); } missing.ConverterString = s; return(missing); #endif }
public static ReflectType Create(Type t) { if (t.IsPrimitive) { return(null); } if (t.IsEnum) { return(null); } if (primitiveTypes.Contains(t)) { return(null); } ReflectType rt; if (lookup.TryGetValue(t, out rt) == false) { rt = new ReflectType(); rt.Fields = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); lookup.Add(t, rt); } return(rt); }
void BegingSurrogate(ReflectType ots, object o) { for (int i = 0; i < currentSurrogates.Count; i++) { var t = currentSurrogates[i]; if (t.Item2 == o) { throw new ArgumentException($"Failed to write object({o}) with surrogate({ots.Surrogate}), as it reference itself."); } } currentSurrogates.Add(Tuple.Create(ots, o)); }
internal Missing(ReflectType type) { this.Type = type; foreach (var m in type.RuntimeMembers) { var mm = new Member { Name = m.Name, Type = m.Type, }; Members.Add(mm); } }
/// <summary> /// Generates the C# class that can be used to deserialize all given types. /// </summary> /// <param name="namespace">The namespace of the generated class.</param> /// <param name="types">The types that will be rewritten with only the serialization information.</param> /// <returns>A generated C# code file as string.</returns> public static string GenerateCSharpCode(string @namespace, params Type[] types) { var ctxt = new ObjectContext(); foreach (var t in types) { var rt = ReflectType.GetType(t); ctxt.RecursizeAdd(rt); } var sb = new StringBuilder(256); ctxt.GenerateCSharpCode(new StringWriter(sb), @namespace); return(sb.ToString()); }
private static void FillProperties(Type type, ReflectType newType, ReflectAssembly newassembly, ReflectNamespace currNamespace) { foreach (var propertyInfo in type.GetProperties()) { // Finds or crates a new Type on this assembly Tuple <ReflectNamespace, ReflectAssembly> asmns = FindNamespaceAndAssembly(propertyInfo.PropertyType); newType.Properties.Add(new ReflectProperty() { Name = propertyInfo.Name, Type = AddNewSimpleReflectType(propertyInfo.PropertyType, asmns.Item2, asmns.Item1) }); } }
private static void FillFields(Type type, ReflectType newType, ReflectAssembly newassembly, ReflectNamespace currNamespace) { foreach (var fieldInfo in type.GetFields()) { // Finds or crates a new Type on this assembly Tuple <ReflectNamespace, ReflectAssembly> asmns = FindNamespaceAndAssembly(fieldInfo.FieldType); newType.Fields.Add(new ReflectField() { Name = fieldInfo.Name, Type = AddNewSimpleReflectType(fieldInfo.FieldType, asmns.Item2, asmns.Item1) }); } }
private static ReflectType AddNewSimpleReflectType(Type type, ReflectAssembly newassembly, ReflectNamespace currNamespace) { var newType = new ReflectType() { Name = type.Name, FullName = type.FullName, Namespace = currNamespace, Assembly = newassembly, Contructors = new List <ReflectMethod>(), Methods = new List <ReflectMethod>(), Fields = new List <ReflectField>(), Properties = new List <ReflectProperty>(), Events = new List <ReflectEvent>(), CSharpName = ToGenericTypeString(type) }; return(newType); }
static void Calculate(StringBuilder sb, String name, Object value, Int32 depth) { var rt = ReflectType.Create(value.GetType()); if (rt == null) { sb.AppendLine(new String(' ', depth * 2) + name + ": " + value.ToString()); } else { sb.AppendLine(new String(' ', depth * 2) + name); foreach (var field in rt.Fields) { Calculate(sb, field.Name, field.GetValue(value), depth + 1); } } }
private static void FillEvents(Type type, ReflectType newType) { foreach (var eventInfo in type.GetEvents()) { // Finds or crates a new Type on this assembly Tuple <ReflectNamespace, ReflectAssembly> asmns = FindNamespaceAndAssembly(eventInfo.EventHandlerType); var newEvent = new ReflectEvent() { Name = eventInfo.Name, Type = AddNewSimpleReflectType(eventInfo.EventHandlerType, asmns.Item2, asmns.Item1) }; newType.Events.Add(newEvent); } }
void ReadCollectionT <T>(ICollection <T> col, ReflectType tT) { var isRO = Reader.ReadBool(); if (isRO) { return; } var count = (int)Reader.ReadVInt(); for (int i = 0; i < count; i++) { var value = Read(tT, null); if (value is T && col != null) { col.Add((T)value); } } }
void ReadDictKV <K, V>(IDictionary <K, V> dict, ReflectType tKey, ReflectType tVal) { var isRO = Reader.ReadBool(); if (isRO) { return; } var count = (int)Reader.ReadVInt(); for (int i = 0; i < count; i++) { var key = Read(tKey, null); var value = Read(tVal, null); if (key is K && value is V && dict != null) { dict.Add((K)key, (V)value); } } }
void WriteConverter(ReflectType ots, object value) { if (value is Missing) { var m = (Missing)value; Write(ReflectType.RString, m.ConverterString); } else { #if !__PCL__ var tc = ots.GetTypeConverter(); if (tc == null) { throw new InvalidOperationException("Failed to get converter."); } var s = tc.ConvertToInvariantString(value); Write(ReflectType.RString, s); #endif } }
void WriteCollection <T>(ICollection <T> list) { Writer.Write(list.IsReadOnly); if (list.IsReadOnly) { return; } var count = list.Count; Writer.WriteVInt(count); var surt = ReflectType.GetType(typeof(T)); foreach (var item in list) { count--; Write(surt, item); } if (count != 0) { throw new ArgumentException($"({list}.Count reported an incorrect value ({list.Count})"); } }
void WriteDictionary <K, V>(IDictionary <K, V> list) { Writer.Write(list.IsReadOnly); if (list.IsReadOnly) { return; } var count = list.Count; Writer.WriteVInt(count); var surk = ReflectType.GetType(typeof(K)); var surv = ReflectType.GetType(typeof(V)); foreach (var kv in list) { count--; Write(surk, kv.Key); Write(surv, kv.Value); } if (count != 0) { throw new ArgumentException($"({list}.Count reported an incorrect value ({list.Count})"); } }
void RecursizeAdd(ReflectType type) { if (Contains(type)) { return; } var id = NewId(); Register(id, type); RecursizeAdd(type.Element); RecursizeAdd(type.Surrogate); RecursizeAdd(type.BaseType); RecursizeAdd(type.Collection1); RecursizeAdd(type.Collection2); foreach (var item in type.GenericArguments) { RecursizeAdd(item); } foreach (var item in type.Members) { RecursizeAdd(item.Type); } }
internal object Read(ReflectType expected, object possibleValue) { object result; ulong oid = 0; if (expected.IsReference) { oid = Reader.ReadVUInt(); if (Context.TryGetObject(oid, out result)) { return(result); } } var actual = expected; if (!expected.IsFinal) // if expected type is not final then write actual type { actual = (ReflectType)Read(ReflectType.RReflectType, null); } object o = null; if (actual.IsIgnored) { o = null; if (oid > 0) { Context.Register(oid, null); } } else if (actual == ReflectType.RReflectType) { var rt = new ReflectType(); Context.Register(oid, rt); o = rt; rt.Read(this); } else if (actual == ReflectType.RType) { var rf = (ReflectType)Read(ReflectType.RReflectType, null); o = rf.Type; Context.Register(oid, o); } else if (actual.IsISerializable && !settings.IgnoreISerializable) { o = ReadISerializable(actual, oid, possibleValue); } else if (actual.HasConverter && !settings.IgnoreTypeConverter) { o = ReadConverter(actual, oid); } else if (actual.HasSurrogate) { o = ReadObject(actual.Surrogate, 0, null); object o2 = o; if (!(o is Missing) && !actual.TryGetOriginal(o, out o2)) { throw new InvalidOperationException("surrogate failure: couldn't get normal instance"); } if (oid != 0) { Context.Register(oid, o2); } o = o2; } else { o = ReadObject(actual, oid, possibleValue); } // since value types are not saved in the context, awake them now! if (oid == 0) { if (o is IDeserialized) { ((IDeserialized)o).Deserialized(); } #if !__PCL__ && !__NETCORE__ if (o is SRS.IDeserializationCallback) { ((SRS.IDeserializationCallback)o).OnDeserialization(null); } #endif } return(o); }
void ToTypeName(StringBuilder sb, ReflectType type) { if (type.IsArray) { ToTypeName(sb, type.Element); for (int i = 1; i < type.ArrayRank; i++) { sb.Append(','); } sb.Append(']'); } else if (type.IsPointer) { ToTypeName(sb, type.Element); sb.Append('*'); } else if (type.IsGenericParameter) { sb.Append('T').Append(type.GenericParameterIndex + 1); } else if (type.Kind == PrimitiveType.Object) { if (type.IsGeneric) { if (type.IsGenericTypeDefinition) { if (type.FastType != null && type.FastType.IsMscorlib) { var sm = 0; var gm = type.TypeName.LastIndexOf('`'); if (type.TypeName.StartsWith("System.ComponentModel.")) { sm = "System.ComponentModel.".Length; } else if (type.TypeName.StartsWith("System.Collections.Generic.")) { sm = "System.Collections.Generic.".Length; } else if (type.TypeName.StartsWith("System.Collections.")) { sm = "System.Collections.".Length; } sb.Append(type.TypeName.Substring(sm, gm - sm)); } else { sb.Append("Type").Append(objectsToIds[type]); } } else { ToTypeName(sb, type.Element); sb.Append('<'); for (int i = 0; i < type.GenericArguments.Count; i++) { if (i > 0) { sb.Append(","); } ToTypeName(sb, type.GenericArguments[i]); } sb.Append('>'); } } else { if (type.Type != null && type.Type == typeof(object)) { sb.Append("object"); } else if (type.FastType != null && type.FastType.IsMscorlib) { sb.Append(type.TypeName); } else { sb.Append("Type").Append(objectsToIds[type]); } } } else { sb.Append(type.ToString()); } }
internal void Write(ReflectType expected, object o) { // 1st write the ID of the object, return if already written if (expected.IsReference) { ulong oid; var isKnown = Context.TryGetId(o, out oid); if (!isKnown) { oid = Context.NewId(); Context.Register(oid, o); } Writer.WriteVInt(oid); if (isKnown) { return; } } // 2nd write class info, **if needed** var ots = expected; if (!expected.IsFinal) { ots = ReflectType.GetType(o); Write(ReflectType.RReflectType, ots); } // finally write the item if (ots.IsIgnored) { // nothing! } else if (ots == ReflectType.RReflectType) { ((ReflectType)o).Write(this); } else if (ots == ReflectType.RType) { var rf = ReflectType.GetType((Type)o); Write(ReflectType.RReflectType, rf); } else if (ots.IsISerializable && !settings.IgnoreISerializable) { WriteISerializable(ots, o); } else if (ots.HasConverter && !settings.IgnoreTypeConverter) { WriteConverter(ots, o); } else if (ots.HasSurrogate) { BegingSurrogate(ots, o); try { object o2; if (!ots.TryGetSurrogate(o, out o2)) { throw new InvalidOperationException("surrogate failure: couldn't get surrogate instance"); } WriteObject(ots.Surrogate, o2); } finally { EndSurrogate(); } } else { WriteObject(ots, o); } }
void GenerateCSharpCode(TextWriter w, ReflectType type, ReflectType isSurrogateFor = null) { if (type.HasConverter && type.IsGeneric) // TODO: IsGeneric only... because not sure... { w.WriteLine($"\tpublic class {ToCSharp(type.TypeName)}Converter : TypeConverter {{"); w.WriteLine("\t\t// TODO ..."); w.WriteLine("\t}"); w.WriteLine($"\t[TypeConverter({ToCSharp(type.TypeName)}Converter)]"); } w.WriteLine($"\t[{nameof(SerializationNameAttribute)}({ToCSharp(type.TypeName)}, {ToCSharp(type.AssemblyName)})]"); if (type.IsEnum) { w.WriteLine($"\tpublic enum Type{objectsToIds[type]} : {type.Element}"); w.WriteLine("\t{"); w.WriteLine("\t\t// TODO: Values need be entered manually ..."); w.WriteLine("\t}"); } else { w.Write("\tpublic "); w.Write(type.IsReference ? "class " : "struct "); w.Write(ToTypeName(type)); if (type.IsGenericTypeDefinition) { w.Write("<"); int N = type.GenericArguments.Count; for (int i = 0; i < N; i++) { if (i > 0) { w.Write(","); } w.Write("T"); w.Write(i + 1); } w.Write(">"); } } int interface_count = 0; Action addInterface = () => { if (interface_count == 0) { interface_count = 1; w.Write(" : "); } else { interface_count++; w.Write(", "); } }; if (type.BaseType != null && type.BaseType != ReflectType.RObject) { addInterface(); w.Write(ToTypeName(type.BaseType)); } if (isSurrogateFor != null) { addInterface(); w.WriteLine($"ISurrogate<{ToTypeName(isSurrogateFor)}>"); } if (type.IsISerializable) { addInterface(); w.Write("ISerializable"); } switch (type.CollectionType) { case ReflectCollectionType.IList: addInterface(); w.Write("Ilist"); break; case ReflectCollectionType.ICollectionT: addInterface(); w.Write($"ICollection<{ToTypeName(type.Collection1)}>"); break; case ReflectCollectionType.IDictionary: addInterface(); w.Write("IDictionary"); break; case ReflectCollectionType.IDictionaryKV: addInterface(); w.Write($"IDictionary<{ToTypeName(type.Collection1)}, {ToTypeName(type.Collection2)}>"); break; } w.WriteLine(); w.WriteLine("\t{"); w.WriteLine($"\t\tpublic Type{objectsToIds[type]}() {{ }}"); if (type.IsISerializable) { w.WriteLine($"\t\tType{objectsToIds[type]}(SerializationInfo info, StreamingContext context) {{ throw new NotImplementedException(\"TODO\"); }}"); w.WriteLine("\t\tvoid ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { throw new NotImplementedException(\"TODO\"); }"); } if (isSurrogateFor != null) { w.WriteLine($"\t\tvoid Initialize({ToTypeName(isSurrogateFor)} value) {{ throw new NotImplementedException(\"TODO\"); }}"); w.WriteLine($"\t\t{ToTypeName(isSurrogateFor)} Instantiate() {{ throw new NotImplementedException(\"TODO\"); }}"); } foreach (var m in type.Members) { w.Write("\t\tpublic "); w.Write(ToTypeName(m.Type)); w.Write(' '); w.Write(m.Name); w.Write(" { get; set; }"); w.WriteLine(); } w.WriteLine("\t}"); if (type.Surrogate != null) { GenerateCSharpCode(w, type.Surrogate, type); } }
void WriteObject(ReflectType ts, object o) { switch (ts.Kind) { default: case PrimitiveType.Object: if (ts.IsArray) { var aa = (Array)o; if (aa.Rank != ts.ArrayRank) { throw new ArgumentException($"{aa} Rank is {aa.Rank} instead of expected {ts.ArrayRank}"); } for (int i = 0; i < ts.ArrayRank; i++) { Writer.WriteVInt(aa.GetLength(i)); } foreach (var item in aa) { Write(ts.Element, item); } } else if (ts.IsNullable) { if (o == null) { Writer.Write(false); } else { Writer.Write(true); Write(ts.GenericArguments[0], o); } } else if (ts.IsEnum) { // TODO: Missing for Enum WriteObject(ts.Element, o); } else { if (o is Missing) { var miss = (Missing)o; foreach (var f in miss.Members) { Write(f.Type, f.Value); } var colt = ts.CollectionInterface; switch (colt.CollectionType) { case ReflectCollectionType.IList: case ReflectCollectionType.ICollectionT: Writer.WriteVInt(miss.Collection.Count); var coll = colt.Collection1 ?? ReflectType.RObject; foreach (var item in miss.Collection) { Write(coll, item.Item1); } break; case ReflectCollectionType.IDictionary: case ReflectCollectionType.IDictionaryKV: Writer.WriteVInt(miss.Collection.Count); var coll1 = colt.Collection1 ?? ReflectType.RObject; var coll2 = colt.Collection2 ?? ReflectType.RObject; foreach (var item in miss.Collection) { Write(coll1, item.Item1); Write(coll2, item.Item2); } break; } } else { foreach (var m in ts.RuntimeMembers) { var p = m.RuntimeMember.GetValue(o); Write(m.Type, p); } var colt = ts.CollectionInterface; switch (colt.CollectionType) { case ReflectCollectionType.IList: WriteList((IList)o); break; case ReflectCollectionType.IDictionary: WriteDict((IDictionary)o); break; case ReflectCollectionType.ICollectionT: if (colt.listWrite == null) { colt.listWrite = FastMethod.GetMethod(GetType().TryGetMethods("WriteCollection", new[] { colt.Collection1.Type }, ts.Type).First()); } if (colt.listWrite != null) { colt.listWrite.Invoke(this, o); } break; case ReflectCollectionType.IDictionaryKV: if (colt.listWrite == null) { colt.listWrite = FastMethod.GetMethod(GetType().TryGetMethods("WriteDictionary", new[] { colt.Collection1.Type, colt.Collection2.Type }, ts.Type).First()); } if (colt.listWrite != null) { colt.listWrite.Invoke(this, o); } break; } } } break; case PrimitiveType.String: Writer.Write((string)o); break; case PrimitiveType.Bytes: Writer.Write((byte[])o); break; case PrimitiveType.Guid: Writer.Write((Guid)o); break; case PrimitiveType.Bool: Writer.Write((bool)o); break; case PrimitiveType.Char: Writer.Write((char)o); break; case PrimitiveType.Byte: Writer.Write((byte)o); break; case PrimitiveType.SByte: Writer.Write((sbyte)o); break; case PrimitiveType.Int16: Writer.Write((short)o); break; case PrimitiveType.UInt16: Writer.Write((ushort)o); break; case PrimitiveType.Int32: Writer.Write((int)o); break; case PrimitiveType.UInt32: Writer.Write((uint)o); break; case PrimitiveType.Int64: Writer.Write((long)o); break; case PrimitiveType.UInt64: Writer.Write((ulong)o); break; case PrimitiveType.Single: Writer.Write((float)o); break; case PrimitiveType.Double: Writer.Write((double)o); break; case PrimitiveType.Decimal: Writer.Write((decimal)o); break; } }
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 }
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())); } }