public void ReadObjectInline(object obj) { typeStack.Clear(); try { var zero = br.Read7BitEncodedLong(); if (zero != 0) { throw new InvalidDataException(); } var idx = objects.Count; objects.Add(obj); var type = (Type)ReadObjectInternal(typeof(Type)); foreach (var field in BinSerCommon.GetFields(type)) { var val = ReadObjectInternal(field.FieldType); field.SetValue(obj, val); } } catch (Exception ex) { throw CreateDeserializationException(ex); } }
private Action <BinSerSerializer, object> GetWriteEachField(Type type) { var q = _writeEachFieldCache.TryGetValue(type); if (q == null) { /* * var assemblyName = new AssemblyName("An.Assembly"); * var appDomain = AppDomain.CurrentDomain; * var assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); * var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, "tonydinozzo.dll"); * var typeBuilder = moduleBuilder.DefineType("MyClass", TypeAttributes.Public | TypeAttributes.Class); * var method = typeBuilder.DefineMethod("Demow", MethodAttributes.Public | MethodAttributes.Static, (Type)null, new[] { typeof(BinSerSerializer), typeof(object) }); */ var method = new DynamicMethod("WriteEachField", null, new[] { typeof(BinSerSerializer), typeof(object) }, true); var gen = method.GetILGenerator(); gen.DeclareLocal(type); gen.Emit(OpCodes.Ldarg_1); if (type.IsValueType()) { gen.Emit(OpCodes.Unbox_Any, type); } else { gen.Emit(OpCodes.Castclass, type); } gen.Emit(OpCodes.Stloc_0); foreach (var field in BinSerCommon.GetFields(type)) { gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldloc_0); gen.Emit(OpCodes.Ldfld, field); if (field.FieldType.IsValueType()) { gen.Emit(OpCodes.Box, field.FieldType); } gen.Emit(OpCodes.Ldtoken, field.FieldType); gen.Emit(OpCodes.Call, BinSerCommon.GetTypeFromHandleMethod); gen.Emit(OpCodes.Callvirt, writeObjMethod); } gen.Emit(OpCodes.Ret); q = (Action <BinSerSerializer, object>)method.CreateDelegate(typeof(Action <BinSerSerializer, object>)); /* var t = typeBuilder.CreateType(); * assemblyBuilder.Save("tonydinozzo.dll"); */ _writeEachFieldCache.TryAdd(type, q); } return(q); }
private void WriteStructInternal(object value) { Sanity.Assert(!(value is IntPtr)); Sanity.Assert(!(value is UIntPtr)); var type = value.GetType(); if (value is bool) { bw.Write7BitEncodedLong((bool)value ? 1 : 0); } else if (value is char) { bw.Write7BitEncodedLong((char)value); } else if (value is double) { bw.Write((double)value); } else if (value is float) { bw.Write((float)value); } else if (value is decimal) { bw.Write((decimal)value); } else if (value is sbyte) { bw.Write7BitEncodedLong((sbyte)value); } else if (value is byte) { bw.Write7BitEncodedLong((byte)value); } else if (value is short) { bw.Write7BitEncodedLong((short)value); } else if (value is ushort) { bw.Write7BitEncodedLong((ushort)value); } else if (value is int) { bw.Write7BitEncodedLong((int)value); } else if (value is uint) { bw.Write7BitEncodedLong((uint)value); } else if (value is long) { bw.Write7BitEncodedLong((long)value); } else if (value is ulong) { bw.Write((ulong)value); } else if (type.IsEnum()) { var bak = Enum.GetUnderlyingType(type); if (bak == typeof(ulong)) { bw.Write((ulong)Convert.ChangeType(value, typeof(ulong))); } else { bw.Write7BitEncodedLong((long)Convert.ChangeType(value, typeof(long))); } } else { AddToObjectStack(value); if (BinSerCommon.Configuration_EmitSerializer) { var w = GetWriteEachField(type); w(this, value); } else { foreach (var field in BinSerCommon.GetFields(type)) { var v = field.GetValue(value); WriteObjectInternal(v, field.FieldType); } } objectStack.RemoveAt(objectStack.Count - 1); } }
internal void WriteObjectInternal(object obj, Type expectedType) { if (obj != null && obj.GetType().IsArray&& ((Array)obj).GetLength(0) > 100) { } Sanity.Assert(obj == null || obj.GetType() != PointerType); var type = obj != null?obj.GetType() : null; if (obj != null && !expectedType.IsValueType()) { int idx; if (objects.TryGetValue(obj, out idx)) { bw.Write7BitEncodedLong(idx); } else { if (Configuration_WriteObjectListDuringSerialization) { try { Console.WriteLine(obj.ToString()); } catch (Exception) { } } //Stats_ObjectCountByType.Increment(obj.GetType()); bw.Write7BitEncodedLong(0); lastObjectId++; objects[obj] = lastObjectId; WriteObjectInternal(type, typeof(Type)); AddToObjectStack(obj); if (type.IsArray) { var arr = (Array)obj; bw.Write7BitEncodedLong(arr.Length); //Stats_ArraySizes.Increment(arr.GetType(), arr.Length); var elemType = type.GetElementType(); for (int i = 0; i < arr.Length; i++) { WriteObjectInternal(arr.GetValue(i), elemType); } } else if (type == typeof(string)) { bw.Write((string)obj); } else if (obj is Delegate) { var deleg = (MulticastDelegate)obj; var ilist = deleg.GetInvocationList(); if (ilist != null && (ilist.Length != 1 || deleg != ilist[0])) { WriteObjectInternal(ilist); } else { WriteObjectInternal(deleg.GetMethodInfo()); WriteObjectInternal(deleg.Target, typeof(object)); } } else if (type == typeof(WeakReference)) { WriteObjectInternal(((WeakReference)obj).Target); } else if (type.IsGenericType() && type.GetGenericTypeDefinition() == typeof(WeakReference <>)) { var method = type.GetMethod("TryGetTarget"); var args = new object[1]; method.Invoke(obj, args); WriteObjectInternal(args[0]); } else { var writer = BinSerCommon.customWriters.TryGetValue(type); if (writer == null && type.IsGenericType()) { writer = BinSerCommon.customWriters.TryGetValue(type.GetGenericTypeDefinition()); } if (writer != null) { writer(this, obj); } else { if (obj is Attribute) { throw new ArgumentException("Serialization of Attribute objects is disallowed."); } var ser = obj as IHasBinSerCallbacks; if (ser != null) { ser.OnSerializing(); } //if (type.Is<Task>()) Debugger.Break(); if (BinSerCommon.Configuration_EmitSerializer) { var w = GetWriteEachField(type); w(this, obj); } else { foreach (var field in BinSerCommon.GetFields(type)) { var v = field.GetValue(obj); WriteObjectInternal(v, field.FieldType); } } } } objectStack.RemoveAt(objectStack.Count - 1); } } else if (expectedType.IsGenericType() && expectedType.GetGenericTypeDefinition() == typeof(Nullable <>)) { if (obj != null) { bw.Write7BitEncodedLong(1); WriteStructInternal(obj); } else { bw.Write7BitEncodedLong(0); } } else if (expectedType.IsValueType()) { WriteStructInternal(obj); } else if (obj == null) { bw.Write7BitEncodedLong(1); } else { Sanity.ShouldntHaveHappened(); } }
private object ReadStructInternal(Type type) { if (type == typeof(bool)) { return(br.Read7BitEncodedLong() != 0); } else if (type == typeof(char)) { return((char)br.Read7BitEncodedLong()); } else if (type == typeof(float)) { return(br.ReadSingle()); } else if (type == typeof(double)) { return(br.ReadDouble()); } else if (type == typeof(decimal)) { return(br.ReadDecimal()); } else if (type == typeof(sbyte)) { return((sbyte)br.Read7BitEncodedLong()); } else if (type == typeof(byte)) { return((byte)br.Read7BitEncodedLong()); } else if (type == typeof(short)) { return((short)br.Read7BitEncodedLong()); } else if (type == typeof(ushort)) { return((ushort)br.Read7BitEncodedLong()); } else if (type == typeof(int)) { return((int)br.Read7BitEncodedLong()); } else if (type == typeof(uint)) { return((uint)br.Read7BitEncodedLong()); } else if (type == typeof(long)) { return((long)br.Read7BitEncodedLong()); } else if (type == typeof(ulong)) { return(br.ReadUInt64()); } var v = Activator.CreateInstance(type); foreach (var field in BinSerCommon.GetFields(type)) { var fieldval = ReadObjectInternal(field.FieldType); field.SetValue(v, fieldval); } return(v); }
internal object ReadObjectInternalImpl(Type expectedType) { var expectedTypeInfo = expectedType.GetTypeInfo(); if (expectedTypeInfo.IsValueType) { if (expectedTypeInfo.IsGenericType && expectedTypeInfo.GetGenericTypeDefinition() == typeof(Nullable <>)) { if (br.Read7BitEncodedLong() == 1) { return(ReadStruct(Nullable.GetUnderlyingType(expectedType))); } else { return(null); } } else { return(ReadStruct(expectedType)); } } else { var idx = (int)br.Read7BitEncodedLong(); if (idx == 1) { return(null); } else if (idx != 0) { return(objects[idx]); } else { idx = objects.Count; objects.Add(null); var type = (Type)ReadObjectInternal(typeof(Type)); object obj; if (type.Is <Delegate>()) { var f = ReadObjectInternal <object>(); var invocationList = f as Delegate[]; if (invocationList != null) { obj = Delegate.Combine(invocationList); } else { var method = (MethodInfo)f; var methodParamTypes = method.GetParameters().Select(x => x.ParameterType).ToList(); var target = ReadObjectInternal <object>(); var funcBase = type.IsGenericType() ? type.GetGenericTypeDefinition() : null; var genargs = funcBase != null?funcBase.GetGenericArguments() : null; Type reducerType = null; if (funcBase == typeof(Action) && methodParamTypes.Count == 1) { reducerType = typeof(SignatureReducerAction <>); } else if (funcBase == typeof(Action <>) && methodParamTypes.Count == 2) { reducerType = typeof(SignatureReducerAction <,>); } else if (funcBase == typeof(Action <,>) && methodParamTypes.Count == 3) { reducerType = typeof(SignatureReducerAction <, ,>); } else if (funcBase == typeof(Func <>) && methodParamTypes.Count == 1) { methodParamTypes.Add(method.ReturnType); reducerType = typeof(SignatureReducerFunc <,>); } else if (funcBase == typeof(Func <,>) && methodParamTypes.Count == 2) { methodParamTypes.Add(method.ReturnType); reducerType = typeof(SignatureReducerFunc <, ,>); } else if (funcBase == typeof(Func <, ,>) && methodParamTypes.Count == 3) { methodParamTypes.Add(method.ReturnType); reducerType = typeof(SignatureReducerFunc <, , ,>); } if (reducerType != null) { var reducer = Activator.CreateInstance(reducerType.MakeGenericTypeFast(methodParamTypes.ToArray()), new object[] { method }); Sanity.Assert(target == null); var call = reducer.GetType().GetMethod("Call", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); return(call.CreateDelegate(type, reducer)); } try { if (target != null) { obj = method.CreateDelegate(type, target); } else { obj = method.CreateDelegate(type); } } catch (Exception ex) { throw new Exception("Cannot create delegate of type " + type.FullName + " for method " + method.DeclaringType.FullName + "::" + method.Name + " - target: " + (target != null ? target.GetType().FullName : "(none)"), ex); } } } else if (type == typeof(string)) { obj = br.ReadString(); } else if (type == typeof(WeakReference)) { var target = ReadObjectInternal <object>(); obj = new WeakReference(target); } else if (type.IsGenericType() && type.GetGenericTypeDefinition() == typeof(WeakReference <>)) { var target = ReadObjectInternal <object>(); obj = Activator.CreateInstance(type, new object[] { target }); } else if (type.IsArray) { var elType = type.GetElementType(); var length = br.Read7BitEncodedLong(); var arr = Array.CreateInstance(elType, (int)length); obj = arr; objects[idx] = obj; for (int i = 0; i < length; i++) { arr.SetValue(ReadObjectInternal(elType), i); } } else { var reader = BinSerCommon.customReaders.TryGetValue(type); if (reader == null && type.IsGenericType()) { reader = BinSerCommon.customReaders.TryGetValue(type.GetGenericTypeDefinition()); } if (reader != null) { obj = reader(this, type); } else { #if CORECLR obj = GetUninitializedObject(type); #else obj = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type); #endif objects[idx] = obj; foreach (var field in BinSerCommon.GetFields(type)) { var val = ReadObjectInternal(field.FieldType); field.SetValue(obj, val); } } } if (obj == null) { throw new InvalidDataException("Deserialization of non-null value yielded to null value."); } objects[idx] = obj; return(obj); } } }