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 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); } } }
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(); } }
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); } }