예제 #1
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);
            }
        }
예제 #2
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);
                }
            }
        }
예제 #3
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();
            }
        }
예제 #4
0
        internal async Task <Stream> OpenStreamAsync(bool synchronous, bool skipCache = false, bool linger = true)
        {
            var url = new LazyUri(Url);
            await Utils.CheckLocalFileAccessAsync(url);

            var mgr = this.manager;
            Func <long, Task <HttpResponseMessage> > createStream = null;

#if !STANDALONE && DESKTOP
            if (Caching.AzureApi != null && (mgr == null || !mgr.IsAlive) && !skipCache)
            {
                var container          = Caching.GetAzureContainer(url);
                HashSet <string> files = null;
                if (synchronous)
                {
                    ObjectManager.SynchronizationContext.Send(async() =>
                    {
                        files = await Caching.GetAzureCachedFiles(container);
                    });
                }
                else
                {
                    await ObjectManager.SynchronizationContext.SendAsync(async() =>
                    {
                        files = await Caching.GetAzureCachedFiles(container);
                    });
                }
                var name = Caching.GetFileCachePath(url);
                if (files.Contains(name))
                {
                    createStream = offset => Caching.GetAzureResponseAsync(container, name, offset, this);
                }
            }
            else
#endif
            if (
#if !STANDALONE && DESKTOP
                Caching.AzureApi == null &&
#endif
                !skipCache)
            {
#if DESKTOP
                var cache = Caching.GetFileCachePath(url);

                if (File.Exists(cache))
                {
                    var str = new FileStream(cache, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete);
                    if (str.Length == 0)
                    {
                        var errfile = Path.ChangeExtension(cache, ".err");
                        if (File.Exists(errfile))
                        {
                            str.Dispose();
                            var errlines = File.ReadAllText(errfile);
                            return(new MediaStream(MediaStream.ExceptionFromCachedResponse(errlines), this));
                        }
                    }
                    Sanity.AssertFastReadByte(str);
                    return(str);
                }
#endif
            }

            lock (this)
            {
                if (manager == null)
                {
                    manager = new MediaStreamManager(createStream ?? GetResponseAsync, true);
                }

                var stream = manager.TryCreateStream(this, 0, linger);
                if (stream == null)
                {
                    manager = new MediaStreamManager(createStream ?? GetResponseAsync, true);
                    stream  = manager.TryCreateStream(this, 0, linger);
                    Sanity.Assert(stream != null);
                }
                Sanity.AssertFastReadByte(stream);
                return(stream);
            }
        }