/// <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="nameConverter">Name converter.</param>
 /// <param name="mapper">Mapper.</param>
 /// <param name="serializer">Serializer.</param>
 /// <param name="metaEnabled">Metadata enabled flag.</param>
 /// <param name="keepDeserialized">Whether to cache deserialized value in IPortableObject</param>
 /// <param name="affKeyFieldName">Affinity field key name.</param>
 /// <param name="typedHandler">Typed handler.</param>
 /// <param name="untypedHandler">Untyped handler.</param>
 public PortableFullTypeDescriptor(
     Type type,
     int typeId,
     string typeName,
     bool userType,
     IPortableNameMapper nameConverter,
     IPortableIdMapper mapper,
     IPortableSerializer serializer,
     bool metaEnabled,
     bool keepDeserialized,
     string affKeyFieldName,
     object typedHandler,
     PortableSystemWriteDelegate untypedHandler)
 {
     _type             = type;
     _typeId           = typeId;
     _typeName         = typeName;
     _userType         = userType;
     _nameConverter    = nameConverter;
     _mapper           = mapper;
     _serializer       = serializer;
     _metaEnabled      = metaEnabled;
     _keepDeserialized = keepDeserialized;
     _affKeyFieldName  = affKeyFieldName;
     _typedHandler     = typedHandler;
     _untypedHandler   = untypedHandler;
 }
        /// <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, IPortableNameMapper converter,
                             IPortableIdMapper idMapper)
        {
            if (type.GetInterface(typeof(IPortableMarshalAware).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 = PortableUtils.CleanFieldName(field.Name);

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

                if (idMap.ContainsKey(fieldId))
                {
                    throw new PortableException("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;
        }
Example #3
0
        /// <summary>
        /// Add user type.
        /// </summary>
        /// <param name="cfg">Configuration.</param>
        /// <param name="typeCfg">Type configuration.</param>
        /// <param name="typeResolver">The type resolver.</param>
        /// <param name="dfltSerializer">The default serializer.</param>
        private void AddUserType(PortableConfiguration cfg, PortableTypeConfiguration typeCfg,
                                 TypeResolver typeResolver, IPortableSerializer dfltSerializer)
        {
            // Get converter/mapper/serializer.
            IPortableNameMapper nameMapper = typeCfg.NameMapper ?? cfg.DefaultNameMapper;

            IPortableIdMapper idMapper = typeCfg.IdMapper ?? cfg.DefaultIdMapper;

            bool metaEnabled = typeCfg.MetadataEnabled ?? cfg.DefaultMetadataEnabled;

            bool keepDeserialized = typeCfg.KeepDeserialized ?? cfg.DefaultKeepDeserialized;

            // Try resolving type.
            Type type = typeResolver.ResolveType(typeCfg.TypeName, typeCfg.AssemblyName);

            if (type != null)
            {
                // Type is found.
                var typeName = GetTypeName(type);

                int typeId = PortableUtils.TypeId(typeName, nameMapper, idMapper);

                var serializer = typeCfg.Serializer ?? cfg.DefaultSerializer
                                 ?? GetPortableMarshalAwareSerializer(type) ?? dfltSerializer;

                var refSerializer = serializer as PortableReflectiveSerializer;

                if (refSerializer != null)
                {
                    refSerializer.Register(type, typeId, nameMapper, idMapper);
                }

                AddType(type, typeId, typeName, true, metaEnabled, keepDeserialized, nameMapper, idMapper, serializer,
                        typeCfg.AffinityKeyFieldName, null, null);
            }
            else
            {
                // Type is not found.
                string typeName = PortableUtils.SimpleTypeName(typeCfg.TypeName);

                int typeId = PortableUtils.TypeId(typeName, nameMapper, idMapper);

                AddType(null, typeId, typeName, true, metaEnabled, keepDeserialized, nameMapper, idMapper, null,
                        typeCfg.AffinityKeyFieldName, null, null);
            }
        }
Example #4
0
        /// <summary>
        /// Add type.
        /// </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="metaEnabled">Metadata enabled flag.</param>
        /// <param name="keepDeserialized">Whether to cache deserialized value in IPortableObject</param>
        /// <param name="nameMapper">Name mapper.</param>
        /// <param name="idMapper">ID mapper.</param>
        /// <param name="serializer">Serializer.</param>
        /// <param name="affKeyFieldName">Affinity key field name.</param>
        /// <param name="typedHandler">Typed handler.</param>
        /// <param name="untypedHandler">Untyped handler.</param>
        private void AddType(Type type, int typeId, string typeName, bool userType, bool metaEnabled,
                             bool keepDeserialized, IPortableNameMapper nameMapper, IPortableIdMapper idMapper,
                             IPortableSerializer serializer, string affKeyFieldName, object typedHandler,
                             PortableSystemWriteDelegate untypedHandler)
        {
            long typeKey = PortableUtils.TypeKey(userType, typeId);

            if (_idToDesc.ContainsKey(typeKey))
            {
                string type1 = _idToDesc[typeKey].Type != null ? _idToDesc[typeKey].Type.AssemblyQualifiedName : null;
                string type2 = type != null ? type.AssemblyQualifiedName : null;

                throw new PortableException("Conflicting type IDs [type1=" + type1 + ", type2=" + type2 +
                                            ", typeId=" + typeId + ']');
            }

            if (userType && _typeNameToDesc.ContainsKey(typeName))
            {
                throw new PortableException("Conflicting type name: " + typeName);
            }

            IPortableTypeDescriptor descriptor =
                new PortableFullTypeDescriptor(type, typeId, typeName, userType, nameMapper, idMapper, serializer,
                                               metaEnabled, keepDeserialized, affKeyFieldName, typedHandler, untypedHandler);

            if (type != null)
            {
                _typeToDesc[type] = descriptor;
            }

            if (userType)
            {
                _typeNameToDesc[typeName] = descriptor;
            }

            _idToDesc[typeKey] = descriptor;
        }
Example #5
0
        internal void Write <T>(T obj, object handler)
        {
            // Apply detach mode if needed.
            PortableHandleDictionary <object, long> oldHnds = null;

            bool resetDetach = false;

            if (_detach)
            {
                _detach     = false;
                _detachMode = true;
                resetDetach = true;

                oldHnds = _hnds;

                _hnds = null;
            }

            try
            {
                // Write null.
                if (obj == null)
                {
                    _stream.WriteByte(PortableUtils.HdrNull);

                    return;
                }

                if (_builder != null)
                {
                    // Special case for portable object during build.
                    PortableUserObject portObj = obj as PortableUserObject;

                    if (portObj != null)
                    {
                        if (!WriteHandle(_stream.Position, portObj))
                        {
                            _builder.ProcessPortable(_stream, portObj);
                        }

                        return;
                    }

                    // Special case for builder during build.
                    PortableBuilderImpl portBuilder = obj as PortableBuilderImpl;

                    if (portBuilder != null)
                    {
                        if (!WriteHandle(_stream.Position, portBuilder))
                        {
                            _builder.ProcessBuilder(_stream, portBuilder);
                        }

                        return;
                    }
                }

                // Try writting as well-known type.
                if (InvokeHandler(handler, handler as PortableSystemWriteDelegate, obj))
                {
                    return;
                }

                Type type = obj.GetType();

                IPortableTypeDescriptor desc = _marsh.Descriptor(type);

                object typedHandler;
                PortableSystemWriteDelegate untypedHandler;

                if (desc == null)
                {
                    typedHandler   = null;
                    untypedHandler = PortableSystemHandlers.WriteHandler(type);
                }
                else
                {
                    typedHandler   = desc.TypedHandler;
                    untypedHandler = desc.UntypedHandler;
                }

                if (InvokeHandler(typedHandler, untypedHandler, obj))
                {
                    return;
                }

                if (desc == null)
                {
                    if (!type.IsSerializable)
                    {
                        // If neither handler, nor descriptor exist, and not serializable, this is an exception.
                        throw new PortableException("Unsupported object type [type=" + type +
                                                    ", object=" + obj + ']');
                    }

                    Write(new SerializableObjectHolder(obj));

                    return;
                }

                int pos = _stream.Position;

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

                // Write header.
                _stream.WriteByte(PortableUtils.HdrFull);

                _stream.WriteBool(desc.UserType);
                _stream.WriteInt(desc.TypeId);
                _stream.WriteInt(obj.GetHashCode());

                // Skip length as it is not known in the first place.
                _stream.Seek(8, SeekOrigin.Current);

                // Preserve old frame.
                int oldTypeId = _curTypeId;
                IPortableNameMapper      oldConverter = _curConverter;
                IPortableIdMapper        oldMapper    = _curMapper;
                IPortableMetadataHandler oldMetaHnd   = _curMetaHnd;
                bool oldRaw    = _curRaw;
                long oldRawPos = _curRawPos;

                // Push new frame.
                _curTypeId    = desc.TypeId;
                _curConverter = desc.NameConverter;
                _curMapper    = desc.Mapper;
                _curMetaHnd   = desc.MetadataEnabled ? _marsh.MetadataHandler(desc) : null;
                _curRaw       = false;
                _curRawPos    = 0;

                // Write object fields.
                desc.Serializer.WritePortable(obj, this);

                // Calculate and write length.
                int retPos = _stream.Position;

                _stream.Seek(pos + 10, SeekOrigin.Begin);

                int len = retPos - pos;

                _stream.WriteInt(len);

                if (_curRawPos != 0)
                {
                    // When set, it is difference between object head and raw position.
                    _stream.WriteInt((int)(_curRawPos - pos));
                }
                else
                {
                    // When no set, it is equal to object length.
                    _stream.WriteInt(len);
                }

                _stream.Seek(retPos, SeekOrigin.Begin);

                // 13. Collect metadata.
                if (_curMetaHnd != null)
                {
                    IDictionary <string, int> meta = _curMetaHnd.OnObjectWriteFinished();

                    if (meta != null)
                    {
                        SaveMetadata(_curTypeId, desc.TypeName, desc.AffinityKeyFieldName, meta);
                    }
                }

                // Restore old frame.
                _curTypeId    = oldTypeId;
                _curConverter = oldConverter;
                _curMapper    = oldMapper;
                _curMetaHnd   = oldMetaHnd;
                _curRaw       = oldRaw;
                _curRawPos    = oldRawPos;
            }
            finally
            {
                // Restore handles if needed.
                if (resetDetach)
                {
                    // Add newly recorded handles without overriding already existing ones.
                    if (_hnds != null)
                    {
                        if (oldHnds == null)
                        {
                            oldHnds = _hnds;
                        }
                        else
                        {
                            oldHnds.Merge(_hnds);
                        }
                    }

                    _hnds = oldHnds;

                    _detachMode = false;
                }
            }
        }
        /// <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, IPortableNameMapper converter,
            IPortableIdMapper idMapper)
        {
            if (type.GetInterface(typeof(IPortableMarshalAware).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 = PortableUtils.CleanFieldName(field.Name);

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

                if (idMap.ContainsKey(fieldId))
                {
                    throw new PortableException("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;
        }
        private T ReadFullObject <T>(int pos)
        {
            // Read header.
            bool userType = Stream.ReadBool();
            int  typeId   = Stream.ReadInt();
            // ReSharper disable once UnusedVariable
            int hashCode  = Stream.ReadInt();
            int len       = Stream.ReadInt();
            int rawOffset = Stream.ReadInt();

            try
            {
                // Already read this object?
                object hndObj;

                if (_hnds != null && _hnds.TryGetValue(pos, out hndObj))
                {
                    return((T)hndObj);
                }

                if (userType && _mode == PortableMode.ForcePortable)
                {
                    PortableUserObject portObj;

                    if (_detach)
                    {
                        Stream.Seek(pos, SeekOrigin.Begin);

                        portObj = GetPortableUserObject(pos, 0, Stream.ReadByteArray(len));
                    }
                    else
                    {
                        portObj = GetPortableUserObject(pos, pos, Stream.Array());
                    }

                    T obj = _builder == null ? TypeCaster <T> .Cast(portObj) : TypeCaster <T> .Cast(_builder.Child(portObj));

                    AddHandle(pos, obj);

                    return(obj);
                }
                else
                {
                    // Find descriptor.
                    IPortableTypeDescriptor desc;

                    if (!_descs.TryGetValue(PortableUtils.TypeKey(userType, typeId), out desc))
                    {
                        throw new PortableException("Unknown type ID: " + typeId);
                    }

                    // Instantiate object.
                    if (desc.Type == null)
                    {
                        throw new PortableException("No matching type found for object [typeId=" +
                                                    desc.TypeId + ", typeName=" + desc.TypeName + ']');
                    }

                    // Preserve old frame.
                    int oldTypeId    = _curTypeId;
                    int oldPos       = _curPos;
                    int oldRawOffset = _curRawOffset;
                    IPortableNameMapper oldConverter = _curConverter;
                    IPortableIdMapper   oldMapper    = _curMapper;
                    bool oldRaw = _curRaw;

                    // Set new frame.
                    _curTypeId    = typeId;
                    _curPos       = pos;
                    _curRawOffset = rawOffset;
                    _curConverter = desc.NameConverter;
                    _curMapper    = desc.Mapper;
                    _curRaw       = false;

                    // Read object.
                    object obj;

                    var sysSerializer = desc.Serializer as IPortableSystemTypeSerializer;

                    if (sysSerializer != null)
                    {
                        obj = sysSerializer.ReadInstance(this);
                    }
                    else
                    {
                        try
                        {
                            obj = FormatterServices.GetUninitializedObject(desc.Type);

                            // Save handle.
                            AddHandle(pos, obj);
                        }
                        catch (Exception e)
                        {
                            throw new PortableException("Failed to create type instance: " +
                                                        desc.Type.AssemblyQualifiedName, e);
                        }

                        desc.Serializer.ReadPortable(obj, this);
                    }

                    // Restore old frame.
                    _curTypeId    = oldTypeId;
                    _curPos       = oldPos;
                    _curRawOffset = oldRawOffset;
                    _curConverter = oldConverter;
                    _curMapper    = oldMapper;
                    _curRaw       = oldRaw;

                    var wrappedSerializable = obj as SerializableObjectHolder;

                    return(wrappedSerializable != null ? (T)wrappedSerializable.Item : (T)obj);
                }
            }
            finally
            {
                // Advance stream pointer.
                Stream.Seek(pos + len, SeekOrigin.Begin);
            }
        }