Пример #1
0
        /// <summary>
        /// Write enum value.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="val">Enum value.</param>
        public void WriteEnum <T>(T val)
        {
            // ReSharper disable once CompareNonConstrainedGenericWithNull
            if (val == null)
            {
                WriteNullField();
            }
            else
            {
                // Unwrap nullable.
                var valType = val.GetType();
                var type    = Nullable.GetUnderlyingType(valType) ?? valType;

                if (!type.IsEnum)
                {
                    throw new BinaryObjectException("Type is not an enum: " + type);
                }

                var handler = BinarySystemHandlers.GetWriteHandler(type);

                if (handler != null)
                {
                    // All enums except long/ulong.
                    handler.Write(this, val);
                }
                else
                {
                    throw new BinaryObjectException(string.Format("Enum '{0}' has unsupported underlying type '{1}'. " +
                                                                  "Use WriteObject instead of WriteEnum.",
                                                                  type, Enum.GetUnderlyingType(type)));
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Check whether the given object is binarizeble, i.e. it can be serialized with binary marshaller.
        /// </summary>
        /// <param name="obj">Object.</param>
        /// <returns>True if binarizable.</returns>
        internal bool IsBinarizable(object obj)
        {
            if (obj != null)
            {
                Type type = obj.GetType();

                // We assume object as binarizable only in case it has descriptor.
                // Collections, Enums and non-primitive arrays do not have descriptors
                // and this is fine here because we cannot know whether their members are binarizable.
                return(_marsh.GetDescriptor(type) != null || BinarySystemHandlers.GetWriteHandler(type) != null);
            }

            return(true);
        }
Пример #3
0
        /// <summary>
        /// Deserialize object.
        /// </summary>
        /// <param name="res">Deserialized object.</param>
        /// <param name="typeOverride">The type override.
        /// There can be multiple versions of the same type when peer assembly loading is enabled.
        /// Only first one is registered in Marshaller.
        /// This parameter specifies exact type to be instantiated.</param>
        /// <returns>
        /// Deserialized object.
        /// </returns>
        public bool TryDeserialize <T>(out T res, Type typeOverride = null)
        {
            int pos = Stream.Position;

            byte hdr = Stream.ReadByte();

            var doDetach = _detach;  // save detach flag into a var and reset so it does not go deeper

            _detach = false;

            switch (hdr)
            {
            case BinaryUtils.HdrNull:
                res = default(T);

                return(false);

            case BinaryUtils.HdrHnd:
                res = ReadHandleObject <T>(pos, typeOverride);

                return(true);

            case BinaryUtils.HdrFull:
                res = ReadFullObject <T>(pos, typeOverride);

                return(true);

            case BinaryUtils.TypeBinary:
                res = ReadBinaryObject <T>(doDetach);

                return(true);

            case BinaryUtils.TypeEnum:
                res = ReadEnum0 <T>(this, _mode == BinaryMode.ForceBinary);

                return(true);

            case BinaryUtils.TypeBinaryEnum:
                res = ReadEnum0 <T>(this, _mode != BinaryMode.Deserialize);

                return(true);
            }

            if (BinarySystemHandlers.TryReadSystemType(hdr, this, out res))
            {
                return(true);
            }

            throw new BinaryObjectException("Invalid header on deserialization [pos=" + pos + ", hdr=" + hdr + ']');
        }
Пример #4
0
        /// <summary>
        /// Deserialize object.
        /// </summary>
        /// <returns>Deserialized object.</returns>
        public bool TryDeserialize <T>(out T res)
        {
            int pos = Stream.Position;

            byte hdr = Stream.ReadByte();

            var doDetach = _detach;  // save detach flag into a var and reset so it does not go deeper

            _detach = false;

            switch (hdr)
            {
            case BinaryUtils.HdrNull:
                res = default(T);

                return(false);

            case BinaryUtils.HdrHnd:
                res = ReadHandleObject <T>(pos);

                return(true);

            case BinaryUtils.HdrFull:
                res = ReadFullObject <T>(pos);

                return(true);

            case BinaryUtils.TypeBinary:
                res = ReadBinaryObject <T>(doDetach);

                return(true);
            }

            if (BinaryUtils.IsPredefinedType(hdr))
            {
                res = BinarySystemHandlers.ReadSystemType <T>(hdr, this);

                return(true);
            }

            throw new BinaryObjectException("Invalid header on deserialization [pos=" + pos + ", hdr=" + hdr + ']');
        }
Пример #5
0
        /// <summary>
        /// Write object.
        /// </summary>
        /// <param name="obj">Object.</param>
        public void Write <T>(T obj)
        {
            // Handle special case for null.
            // ReSharper disable once CompareNonConstrainedGenericWithNull
            if (obj == null)
            {
                _stream.WriteByte(BinaryUtils.HdrNull);

                return;
            }

            // We use GetType() of a real object instead of typeof(T) to take advantage of
            // automatic Nullable'1 unwrapping.
            Type type = obj.GetType();

            // Handle common case when primitive is written.
            if (type.IsPrimitive)
            {
                WritePrimitive(obj, type);

                return;
            }

            // Handle special case for builder.
            if (WriteBuilderSpecials(obj))
            {
                return;
            }

            // Are we dealing with a well-known type?
            var handler = BinarySystemHandlers.GetWriteHandler(type);

            if (handler != null)
            {
                if (handler.SupportsHandles && WriteHandle(_stream.Position, obj))
                {
                    return;
                }

                handler.Write(this, obj);

                return;
            }

            // Wrap objects as required.
            if (WrapperFunc != null && type != WrapperFunc.Method.ReturnType)
            {
                if (_isInWrapper)
                {
                    _isInWrapper = false;
                }
                else
                {
                    _isInWrapper = true;
                    Write(WrapperFunc(obj));

                    return;
                }
            }

            // Suppose that we faced normal object and perform descriptor lookup.
            var desc = _marsh.GetDescriptor(type);

            // Writing normal object.
            var pos = _stream.Position;

            // Dealing with handles.
            if (desc.Serializer.SupportsHandles && WriteHandle(pos, obj))
            {
                return;
            }

            // Skip header length as not everything is known now
            _stream.Seek(BinaryObjectHeader.Size, SeekOrigin.Current);

            // Write type name for unregistered types
            if (!desc.IsRegistered)
            {
                WriteString(Marshaller.GetTypeName(type));
            }

            var headerSize = _stream.Position - pos;

            // Preserve old frame.
            var oldFrame = _frame;

            // Push new frame.
            _frame.RawPos            = 0;
            _frame.Pos               = pos;
            _frame.Struct            = new BinaryStructureTracker(desc, desc.WriterTypeStructure);
            _frame.HasCustomTypeData = false;

            var schemaIdx = _schema.PushSchema();

            try
            {
                // Write object fields.
                desc.Serializer.WriteBinary(obj, this);
                var dataEnd = _stream.Position;

                // Write schema
                var schemaOffset = dataEnd - pos;

                int schemaId;

                var flags = desc.UserType
                    ? BinaryObjectHeader.Flag.UserType
                    : BinaryObjectHeader.Flag.None;

                if (_frame.HasCustomTypeData)
                {
                    flags |= BinaryObjectHeader.Flag.CustomDotNetType;
                }

                if (Marshaller.CompactFooter && desc.UserType)
                {
                    flags |= BinaryObjectHeader.Flag.CompactFooter;
                }

                var hasSchema = _schema.WriteSchema(_stream, schemaIdx, out schemaId, ref flags);

                if (hasSchema)
                {
                    flags |= BinaryObjectHeader.Flag.HasSchema;

                    // Calculate and write header.
                    if (_frame.RawPos > 0)
                    {
                        _stream.WriteInt(_frame.RawPos - pos); // raw offset is in the last 4 bytes
                    }
                    // Update schema in type descriptor
                    if (desc.Schema.Get(schemaId) == null)
                    {
                        desc.Schema.Add(schemaId, _schema.GetSchema(schemaIdx));
                    }
                }
                else
                {
                    schemaOffset = headerSize;
                }

                if (_frame.RawPos > 0)
                {
                    flags |= BinaryObjectHeader.Flag.HasRaw;
                }

                var len = _stream.Position - pos;

                var hashCode = BinaryArrayEqualityComparer.GetHashCode(Stream, pos + BinaryObjectHeader.Size,
                                                                       dataEnd - pos - BinaryObjectHeader.Size);

                var header = new BinaryObjectHeader(desc.IsRegistered ? desc.TypeId : BinaryTypeId.Unregistered,
                                                    hashCode, len, schemaId, schemaOffset, flags);

                BinaryObjectHeader.Write(header, _stream, pos);

                Stream.Seek(pos + len, SeekOrigin.Begin); // Seek to the end
            }
            finally
            {
                _schema.PopSchema(schemaIdx);
            }

            // Apply structure updates if any.
            _frame.Struct.UpdateWriterStructure(this);

            // Restore old frame.
            _frame = oldFrame;
        }
Пример #6
0
        /// <summary>
        /// Write object.
        /// </summary>
        /// <param name="obj">Object.</param>
        public void Write <T>(T obj)
        {
            // Handle special case for null.
            if (obj == null)
            {
                _stream.WriteByte(BinaryUtils.HdrNull);

                return;
            }

            // We use GetType() of a real object instead of typeof(T) to take advantage of
            // automatic Nullable'1 unwrapping.
            Type type = obj.GetType();

            // Handle common case when primitive is written.
            if (type.IsPrimitive)
            {
                WritePrimitive(obj, type);

                return;
            }

            // Handle special case for builder.
            if (WriteBuilderSpecials(obj))
            {
                return;
            }

            // Suppose that we faced normal object and perform descriptor lookup.
            IBinaryTypeDescriptor desc = type.IsEnum ? null : _marsh.GetDescriptor(type);

            if (desc != null)
            {
                // Writing normal object.
                var pos = _stream.Position;

                // Dealing with handles.
                if (!(desc.Serializer is IBinarySystemTypeSerializer) && WriteHandle(pos, obj))
                {
                    return;
                }

                // Skip header length as not everything is known now
                _stream.Seek(BinaryObjectHeader.Size, SeekOrigin.Current);

                // Preserve old frame.
                int oldTypeId = _curTypeId;
                IBinaryNameMapper oldConverter = _curConverter;
                IBinaryIdMapper   oldMapper    = _curMapper;
                int oldRawPos = _curRawPos;
                var oldPos    = _curPos;

                var oldStruct = _curStruct;

                // Push new frame.
                _curTypeId    = desc.TypeId;
                _curConverter = desc.NameMapper;
                _curMapper    = desc.IdMapper;
                _curRawPos    = 0;
                _curPos       = pos;

                _curStruct = new BinaryStructureTracker(desc, desc.WriterTypeStructure);
                var schemaIdx = _schema.PushSchema();

                try
                {
                    // Write object fields.
                    desc.Serializer.WriteBinary(obj, this);

                    // Write schema
                    var schemaOffset = _stream.Position - pos;

                    int schemaId;

                    var flags = desc.UserType
                        ? BinaryObjectHeader.Flag.UserType
                        : BinaryObjectHeader.Flag.None;

                    var hasSchema = _schema.WriteSchema(_stream, schemaIdx, out schemaId, ref flags);

                    if (hasSchema)
                    {
                        flags |= BinaryObjectHeader.Flag.HasSchema;

                        // Calculate and write header.
                        if (_curRawPos > 0)
                        {
                            _stream.WriteInt(_curRawPos - pos); // raw offset is in the last 4 bytes
                        }
                    }
                    else
                    {
                        schemaOffset = BinaryObjectHeader.Size;
                    }

                    if (_curRawPos > 0)
                    {
                        flags |= BinaryObjectHeader.Flag.HasRaw;
                    }

                    var len = _stream.Position - pos;

                    var header = new BinaryObjectHeader(desc.TypeId, obj.GetHashCode(), len,
                                                        schemaId, schemaOffset, flags);

                    BinaryObjectHeader.Write(header, _stream, pos);

                    Stream.Seek(pos + len, SeekOrigin.Begin); // Seek to the end
                }
                finally
                {
                    _schema.PopSchema(schemaIdx);
                }

                // Apply structure updates if any.
                _curStruct.UpdateWriterStructure(this);

                // Restore old frame.
                _curTypeId    = oldTypeId;
                _curConverter = oldConverter;
                _curMapper    = oldMapper;
                _curRawPos    = oldRawPos;
                _curPos       = oldPos;

                _curStruct = oldStruct;
            }
            else
            {
                // Are we dealing with a well-known type?
                var handler = BinarySystemHandlers.GetWriteHandler(type);

                if (handler == null)  // We did our best, object cannot be marshalled.
                {
                    throw new BinaryObjectException("Unsupported object type [type=" + type + ", object=" + obj + ']');
                }

                handler(this, obj);
            }
        }
Пример #7
0
 /** <inheritDoc /> */
 public IBinaryObjectBuilder SetField <T>(string fieldName, T val)
 {
     return(SetField0(fieldName,
                      new BinaryBuilderField(typeof(T), val, BinarySystemHandlers.GetTypeId(typeof(T)))));
 }