/// <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; }
/// <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); } }
/// <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; }
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); } }