/// <summary>Register type.</summary>
        /// <param name="type">Type.</param>
        /// <param name="typeId">Type ID.</param>
        /// <param name="converter">Name converter.</param>
        /// <param name="idMapper">ID mapper.</param>
        public void Register(Type type, int typeId, IBinaryNameMapper converter,
            IBinaryIdMapper idMapper)
        {
            if (type.GetInterface(typeof(IBinarizable).Name) != null)
                return;

            List<FieldInfo> fields = new List<FieldInfo>();

            Type curType = type;

            while (curType != null)
            {
                foreach (FieldInfo field in curType.GetFields(Flags))
                {
                    if (!field.IsNotSerialized)
                        fields.Add(field);
                }

                curType = curType.BaseType;
            }

            IDictionary<int, string> idMap = new Dictionary<int, string>();

            foreach (FieldInfo field in fields)
            {
                string fieldName = BinaryUtils.CleanFieldName(field.Name);

                int fieldId = BinaryUtils.FieldId(typeId, fieldName, converter, idMapper);

                if (idMap.ContainsKey(fieldId))
                {
                    throw new BinaryObjectException("Conflicting field IDs [type=" +
                        type.Name + ", field1=" + idMap[fieldId] + ", field2=" + fieldName +
                        ", fieldId=" + fieldId + ']');
                }

                idMap[fieldId] = fieldName;
            }

            fields.Sort(Compare);

            Descriptor desc = new Descriptor(fields);

            _types[type] = desc;
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="type">Type.</param>
 /// <param name="typeId">Type ID.</param>
 /// <param name="typeName">Type name.</param>
 /// <param name="userType">User type flag.</param>
 /// <param name="nameMapper">Name converter.</param>
 /// <param name="idMapper">Mapper.</param>
 /// <param name="serializer">Serializer.</param>
 /// <param name="keepDeserialized">Whether to cache deserialized value in IBinaryObject</param>
 /// <param name="affKeyFieldName">Affinity field key name.</param>
 public BinaryFullTypeDescriptor(
     Type type, 
     int typeId, 
     string typeName, 
     bool userType, 
     IBinaryNameMapper nameMapper, 
     IBinaryIdMapper idMapper, 
     IBinarySerializer serializer, 
     bool keepDeserialized, 
     string affKeyFieldName)
 {
     _type = type;
     _typeId = typeId;
     _typeName = typeName;
     _userType = userType;
     _nameMapper = nameMapper;
     _idMapper = idMapper;
     _serializer = serializer;
     _keepDeserialized = keepDeserialized;
     _affKeyFieldName = affKeyFieldName;
 }
Example #3
0
 /// <summary>
 /// Gets the name of the type according to current name mapper.
 /// See also <see cref="ResolveType"/>.
 /// </summary>
 public string GetTypeName(Type type, IBinaryNameMapper mapper = null)
 {
     return(GetTypeName(type.AssemblyQualifiedName, mapper));
 }
Example #4
0
        /// <summary>
        /// Gets the serializer.
        /// </summary>
        private static IBinarySerializerInternal GetSerializer(BinaryConfiguration cfg,
                                                               BinaryTypeConfiguration typeCfg, Type type, int typeId, IBinaryNameMapper nameMapper,
                                                               IBinaryIdMapper idMapper, ILogger log)
        {
            var serializer = (typeCfg != null ? typeCfg.Serializer : null) ??
                             (cfg != null ? cfg.Serializer : null);

            if (serializer == null)
            {
                if (type.GetInterfaces().Contains(typeof(IBinarizable)))
                {
                    return(BinarizableSerializer.Instance);
                }

                if (type.GetInterfaces().Contains(typeof(ISerializable)))
                {
                    LogSerializableWarning(type, log);

                    return(new SerializableSerializer(type));
                }

                serializer = new BinaryReflectiveSerializer();
            }

            var refSerializer = serializer as BinaryReflectiveSerializer;

            return(refSerializer != null
                ? refSerializer.Register(type, typeId, nameMapper, idMapper)
                : new UserSerializerProxy(serializer));
        }
Example #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 enums.
            if (type.IsEnum)
            {
                WriteEnum(obj);

                return;
            }

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

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

            if (desc != null)
            {
                // 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);

                // 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);
                    var dataEnd = _stream.Position;

                    // Write schema
                    var schemaOffset = dataEnd - pos;

                    int schemaId;

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

                    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 (_curRawPos > 0)
                        {
                            _stream.WriteInt(_curRawPos - 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 = BinaryObjectHeader.Size;
                    }

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

                    var len = _stream.Position - pos;

                    var hashCode = desc.EqualityComparer != null
                        ? desc.EqualityComparer.GetHashCode(Stream, pos + BinaryObjectHeader.Size,
                                                            dataEnd - pos - BinaryObjectHeader.Size, _schema, schemaIdx, _marsh, desc)
                        : obj.GetHashCode();

                    var header = new BinaryObjectHeader(desc.TypeId, 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.
                _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 BinaryUtils.GetUnsupportedTypeException(type, obj);
                }

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

                handler.Write(this, obj);
            }
        }
Example #6
0
        /// <summary>
        /// Gets the serializer.
        /// </summary>
        private static IBinarySerializerInternal GetSerializer(BinaryConfiguration cfg, BinaryTypeConfiguration typeCfg,
                                                               Type type, int typeId, IBinaryNameMapper nameMapper, IBinaryIdMapper idMapper)
        {
            var serializer = typeCfg.Serializer ?? cfg.DefaultSerializer;

            if (serializer == null)
            {
                if (type.GetInterfaces().Contains(typeof(IBinarizable)))
                {
                    return(BinarizableSerializer.Instance);
                }

                serializer = new BinaryReflectiveSerializer();
            }

            var refSerializer = serializer as BinaryReflectiveSerializer;

            return(refSerializer != null
                ? refSerializer.Register(type, typeId, nameMapper, idMapper)
                : new UserSerializerProxy(serializer));
        }