private Type GetElementType(DataTypes dt, BinaryReader br, DeserializationManager manager, bool allowOpenTypes, out DataTypeDescriptor existingDescriptor) { existingDescriptor = null; switch (dt & ~DataTypes.Store7BitEncoded) { case DataTypes.Bool: return(Reflector.BoolType); case DataTypes.Int8: return(Reflector.SByteType); case DataTypes.UInt8: return(Reflector.ByteType); case DataTypes.Int16: return(Reflector.ShortType); case DataTypes.UInt16: return(Reflector.UShortType); case DataTypes.Int32: return(Reflector.IntType); case DataTypes.UInt32: return(Reflector.UIntType); case DataTypes.Int64: return(Reflector.LongType); case DataTypes.UInt64: return(Reflector.ULongType); case DataTypes.Char: return(Reflector.CharType); case DataTypes.String: return(Reflector.StringType); case DataTypes.Single: return(Reflector.FloatType); case DataTypes.Double: return(Reflector.DoubleType); case DataTypes.Decimal: return(Reflector.DecimalType); case DataTypes.DateTime: return(Reflector.DateTimeType); case DataTypes.DBNull: return(Reflector.DBNullType); case DataTypes.IntPtr: return(Reflector.IntPtrType); case DataTypes.UIntPtr: return(Reflector.UIntPtrType); case DataTypes.Version: return(typeof(Version)); case DataTypes.Guid: return(Reflector.GuidType); case DataTypes.TimeSpan: return(Reflector.TimeSpanType); case DataTypes.DateTimeOffset: return(Reflector.DateTimeOffsetType); case DataTypes.Uri: return(typeof(Uri)); case DataTypes.BitArray: return(Reflector.BitArrayType); case DataTypes.BitVector32: return(typeof(BitVector32)); case DataTypes.BitVector32Section: return(typeof(BitVector32.Section)); case DataTypes.StringBuilder: return(typeof(StringBuilder)); case DataTypes.Object: return(Reflector.ObjectType); case DataTypes.Void: return(Reflector.VoidType); case DataTypes.RuntimeType: return(Reflector.RuntimeType); case DataTypes.Pointer: return(ElementDescriptor.DecodeType(br, manager, allowOpenTypes).MakePointerType()); case DataTypes.ByRef: return(ElementDescriptor.DecodeType(br, manager, allowOpenTypes).MakeByRefType()); case DataTypes.BinarySerializable: case DataTypes.RawStruct: case DataTypes.RecursiveObjectGraph: existingDescriptor = manager.ReadType(br, allowOpenTypes); return(existingDescriptor.Type); default: // nullable if (IsNullable(dt)) { IsNullable = true; Type underlyingType = GetElementType(dt & ~DataTypes.Nullable, br, manager, allowOpenTypes, out existingDescriptor); return(Reflector.NullableType.GetGenericType(underlyingType)); } // enum if (IsEnum(dt)) { existingDescriptor = manager.ReadType(br, allowOpenTypes); return(existingDescriptor.Type); } return(Throw.SerializationException <Type>(Res.BinarySerializationCannotDecodeDataType(DataTypeToString(ElementDataType)))); } }
internal object InitializeCollection(BinaryReader br, bool addToCache, DataTypeDescriptor descriptor, DeserializationManager manager, out int count) { object result; // KeyValuePair, DictionaryEntry if (IsSingleElement) { // Note: If addToCache is true, then the key-value may contain itself via references. // That's why we create the instance first and then set Key and Value (just like at object graphs). result = Activator.CreateInstance(descriptor.GetTypeToCreate()); if (addToCache) { manager.AddObjectToCache(result); } count = 1; return(result); } // 1.) Count count = Read7BitInt(br); // 2.) Capacity int capacity = HasCapacity ? Read7BitInt(br) : count; // 3.) Case sensitivity bool caseInsensitive = false; if (HasCaseInsensitivity) { caseInsensitive = br.ReadBoolean(); } // 4.) Read-only if (HasReadOnly) { descriptor.IsReadOnly = br.ReadBoolean(); } // In the ID cache the collection comes first and then the comparer so we add a placeholder to the cache. // Unlike for KeyValuePairs this works here because we can assume that a comparer does not reference the collection. int id = 0; if (addToCache) { manager.AddObjectToCache(null, out id); } // 5.) Comparer object comparer = HasAnyComparer ? br.ReadBoolean() ? IsNonNullDefaultComparer ? GetDefaultComparer(descriptor.Type) : null : manager.ReadWithType(br) : null; result = CreateCollection(descriptor, capacity, caseInsensitive, comparer); if (id != 0) { manager.ReplaceObjectInCache(id, result); } return(result); }
/// <summary> /// Decodes self and element types /// </summary> internal Type DecodeType(BinaryReader br, DeserializationManager manager, bool allowOpenTypes = false) { DataTypeDescriptor existingDescriptor; // Simple or impure type. Handling generics occurs in recursive ReadType if needed. if (CollectionDataType == DataTypes.Null) { Type = GetElementType(ElementDataType, br, manager, allowOpenTypes, out existingDescriptor); StoredType = existingDescriptor?.StoredType; return(Type); } Type result; // generic type definition if (ElementDataType == DataTypes.GenericTypeDefinition) { result = GetCollectionType(CollectionDataType); } else { // simple collection element or dictionary key: Since in DataTypes the element is encoded together with the collection // the element type descriptor was not created in the constructor. We create it now. if (ElementDataType != DataTypes.Null) { ElementDescriptor = new DataTypeDescriptor(ElementDataType, GetElementType(ElementDataType, br, manager, allowOpenTypes, out existingDescriptor), this); ElementDescriptor.StoredType = existingDescriptor?.StoredType; } // complex element type: recursive decoding else { ElementDescriptor.DecodeType(br, manager, allowOpenTypes); } // Dictionary TValue if (IsDictionary) { ValueDescriptor.DecodeType(br, manager, allowOpenTypes); } if (IsArray) { // 0 means zero based 1D array Rank = br.ReadByte(); return(Type = Rank == 0 ? ElementDescriptor.Type.MakeArrayType() : ElementDescriptor.Type.MakeArrayType(Rank)); } result = GetCollectionType(CollectionDataType); bool isNullable = IsNullable = result.IsNullable(); if (!result.ContainsGenericParameters) { return(Type = result); } Type typeDef = isNullable ? result.GetGenericArguments()[0] : result; result = typeDef.GetGenericArguments().Length == 1 ? typeDef.GetGenericType(ElementDescriptor.Type) : typeDef.GetGenericType(ElementDescriptor.Type, ValueDescriptor.Type); result = isNullable ? Reflector.NullableType.GetGenericType(result) : result; } if (result.IsGenericTypeDefinition) { result = manager.HandleGenericTypeDef(br, new DataTypeDescriptor(result), allowOpenTypes, false).Type; } return(Type = result); }