예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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();
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
                }
            }
        }