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))));
                }
            }
Exemple #2
0
            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);
            }