public object Deserialize(BinaryReader reader) { if (reader.ReadInt32() != magic) throw new SerializationException("The data cannot be read by FastSerializer (unknown magic value)"); DeserializationContext context = new DeserializationContext(); context.Reader = reader; context.Objects = new object[reader.ReadInt32()]; context.Types = new Type[reader.ReadInt32()]; string[] assemblyNames = new string[reader.ReadInt32()]; int fixedInstanceCount = reader.ReadInt32(); if (fixedInstanceCount != 0) { if (this.FixedInstances == null || this.FixedInstances.Length != fixedInstanceCount) throw new SerializationException("Number of fixed instances doesn't match"); for (int i = 0; i < fixedInstanceCount; i++) { context.Objects[i + 1] = this.FixedInstances[i]; } } for (int i = 0; i < assemblyNames.Length; i++) { assemblyNames[i] = reader.ReadString(); } int stringTypeID = -1; for (int i = 0; i < context.Types.Length; i++) { byte typeKind = reader.ReadByte(); switch (typeKind) { case Type_ReferenceType: case Type_ValueType: int assemblyID; if (assemblyNames.Length <= ushort.MaxValue) assemblyID = reader.ReadUInt16(); else assemblyID = reader.ReadInt32(); string assemblyName = assemblyNames[assemblyID]; string typeName = reader.ReadString(); Type type; if (SerializationBinder != null) { type = SerializationBinder.BindToType(assemblyName, typeName); } else { type = Assembly.Load(assemblyName).GetType(typeName); } if (type == null) throw new SerializationException("Could not find '" + typeName + "' in '" + assemblyName + "'"); if (typeKind == Type_ValueType && !type.IsValueType) throw new SerializationException("Expected '" + typeName + "' to be a value type, but it is reference type"); if (typeKind == Type_ReferenceType && type.IsValueType) throw new SerializationException("Expected '" + typeName + "' to be a reference type, but it is value type"); context.Types[i] = type; if (type == typeof(string)) stringTypeID = i; break; case Type_SZArray: context.Types[i] = context.Types[context.ReadTypeID()].MakeArrayType(); break; case Type_ParameterizedType: Type genericType = context.Types[context.ReadTypeID()]; int typeParameterCount = genericType.GetGenericArguments().Length; Type[] typeArguments = new Type[typeParameterCount]; for (int j = 0; j < typeArguments.Length; j++) { typeArguments[j] = context.Types[context.ReadTypeID()]; } context.Types[i] = genericType.MakeGenericType(typeArguments); break; default: throw new SerializationException("Unknown type kind"); } } context.DeserializeTypeDescriptions(); int[] typeIDByObjectID = new int[context.Objects.Length]; for (int i = 1 + fixedInstanceCount; i < context.Objects.Length; i++) { int typeID = context.ReadTypeID(); object instance; if (typeID == stringTypeID) { instance = reader.ReadString(); } else { Type type = context.Types[typeID]; if (type.IsArray) { int length = reader.ReadInt32(); instance = Array.CreateInstance(type.GetElementType(), length); } else { instance = FormatterServices.GetUninitializedObject(type); } } context.Objects[i] = instance; typeIDByObjectID[i] = typeID; } List<CustomDeserialization> customDeserializatons = new List<CustomDeserialization>(); ObjectReader[] objectReaders = new ObjectReader[context.Types.Length]; // index: type ID for (int i = 1 + fixedInstanceCount; i < context.Objects.Length; i++) { object instance = context.Objects[i]; int typeID = typeIDByObjectID[i]; Log("0x{2:x6} Read #{0}: {1}", i, context.Types[typeID].Name, reader.BaseStream.Position); ISerializable serializable = instance as ISerializable; if (serializable != null) { Type type = context.Types[typeID]; SerializationInfo info = new SerializationInfo(type, formatterConverter); int count = reader.ReadInt32(); for (int j = 0; j < count; j++) { string name = reader.ReadString(); object val = context.ReadObject(); info.AddValue(name, val); } CustomDeserializationAction action = GetCustomDeserializationAction(type); customDeserializatons.Add(new CustomDeserialization(instance, info, action)); } else { ObjectReader objectReader = objectReaders[typeID]; if (objectReader == null) { objectReader = GetReader(context.Types[typeID]); objectReaders[typeID] = objectReader; } objectReader(context, instance); } } Log("File was read successfully, now running {0} custom deserializations...", customDeserializatons.Count); foreach (CustomDeserialization customDeserializaton in customDeserializatons) { customDeserializaton.Run(streamingContext); } for (int i = 1 + fixedInstanceCount; i < context.Objects.Length; i++) { IDeserializationCallback dc = context.Objects[i] as IDeserializationCallback; if (dc != null) dc.OnDeserialization(null); } return context.ReadObject(); }