public TypeReader(SerializerDataSettings dataSettings, SerializerOptions options, uint maxDepth, ICollection <object> ignoreAttributes, SerializationTypeRegistry typeRegistry, ICollection <string> ignorePropertiesOrPaths = null) { _dataSettings = dataSettings; _options = options; _maxDepth = maxDepth; _ignoreAttributes = ignoreAttributes; _ignorePropertiesOrPaths = ignorePropertiesOrPaths; _typeRegistry = ConvertToTypeRegistry(typeRegistry); _objectReferences = new Dictionary <ushort, object>(); _customSerializers = new Dictionary <Type, Lazy <ICustomSerializer> > { { typeof(Point), new Lazy <ICustomSerializer>(() => new PointSerializer()) }, { typeof(Enum), new Lazy <ICustomSerializer>(() => new EnumSerializer()) }, { typeof(XDocument), new Lazy <ICustomSerializer>(() => new XDocumentSerializer()) }, }; }
public TypeWriter(uint maxDepth, SerializerDataSettings dataSettings, SerializerOptions options, ICollection <object> ignoreAttributes, TypeDescriptors typeDescriptors, ICollection <string> ignorePropertiesOrPaths = null) { _debugWriter = new DebugReportWriter(); _maxDepth = maxDepth; _dataSettings = dataSettings; _options = options; _ignoreAttributes = ignoreAttributes; _ignorePropertiesOrPaths = ignorePropertiesOrPaths; _typeDescriptors = typeDescriptors; _referenceTracker = new ObjectReferenceTracker(); _customSerializers = new Dictionary <Type, Lazy <ICustomSerializer> > { { typeof(Point), new Lazy <ICustomSerializer>(() => new PointSerializer()) }, { typeof(Enum), new Lazy <ICustomSerializer>(() => new EnumSerializer()) }, { typeof(XDocument), new Lazy <ICustomSerializer>(() => new XDocumentSerializer()) }, }; }
/// <summary> /// Read a single chunk of data, recursively. /// </summary> /// <param name="reader"></param> /// <returns></returns> private bool ReadChunk(BinaryReader reader, TypeDescriptors typeDescriptors, SerializerDataSettings dataSettings) { var isChunkValid = true; var objectTypeIdByte = reader.ReadByte(); var objectTypeId = (TypeId)objectTypeIdByte; var isTypeMapped = TypeUtil.IsTypeMapped(objectTypeId); var isTypeDescriptorMap = TypeUtil.IsTypeDescriptorMap(objectTypeId); uint length = 0; if (dataSettings.BitwiseHasFlag(SerializerDataSettings.Compact)) { length = reader.ReadUInt16(); } else { length = reader.ReadUInt32(); } var lengthStartPosition = reader.BaseStream.Position; ushort objectReferenceId = 0; ushort typeDescriptorId = 0; if (isTypeDescriptorMap) { uint dataLength = 0; if (dataSettings.BitwiseHasFlag(SerializerDataSettings.Compact)) { dataLength = length - sizeof(ushort); } else { dataLength = length - sizeof(uint); } // read in the type descriptor map var typeDescriptorMap = TypeReader.GetTypeDescriptorMap(reader, dataLength); // continue reading the data return(ReadChunk(reader, typeDescriptorMap, dataSettings)); } else { // read the object reference id objectReferenceId = reader.ReadUInt16(); } // only interfaces can store type descriptors if (typeDescriptors != null && isTypeMapped) { typeDescriptorId = reader.ReadUInt16(); if (!typeDescriptors.Contains(typeDescriptorId)) { return(false); } } // value type if (length > 0) { switch (objectTypeId) { // these types may contain additional chunks, only value types may not. case TypeId.Array: case TypeId.Tuple: case TypeId.IDictionary: case TypeId.IEnumerable: case TypeId.Struct: case TypeId.Enum: case TypeId.KeyValuePair: case TypeId.Object: isChunkValid = ReadChunk(reader, typeDescriptors, dataSettings); if (!isChunkValid) { return(false); } break; default: // it's not a chunk type, it's a value type isChunkValid = true; break; } if (reader.BaseStream.Position - lengthStartPosition - sizeof(ushort) == 0) { // it's a value type, read the full data byte[] data = null; if (dataSettings.BitwiseHasFlag(SerializerDataSettings.Compact)) { data = reader.ReadBytes((int)(length - Constants.CompactLengthHeaderSize)); } else { data = reader.ReadBytes((int)(length - Constants.LengthHeaderSize)); } } else if (reader.BaseStream.Position < reader.BaseStream.Length) { // read another chunk isChunkValid = ReadChunk(reader, typeDescriptors, dataSettings); if (!isChunkValid) { return(false); } } } return(isChunkValid); }