/// <summary> /// Reads a structural object, including referenced objects. /// </summary> /// <returns>The object that has been read.</returns> protected object ReadStruct() { // Read struct type string objTypeString = this.reader.ReadString(); uint objId = this.reader.ReadUInt32(); bool custom = this.reader.ReadBoolean(); bool surrogate = this.reader.ReadBoolean(); Type objType = this.ResolveType(objTypeString, objId); SerializeType objSerializeType = null; if (objType != null) { objSerializeType = objType.GetSerializeType(); } // Retrieve surrogate if requested ISurrogate objSurrogate = null; if (surrogate && objType != null) { objSurrogate = this.GetSurrogateFor(objType); } // Construct object object obj = null; if (objType != null) { if (objSurrogate != null) { custom = true; // Set fake object reference for surrogate constructor: No self-references allowed here. this.idManager.Inject(null, objId); CustomSerialIO customIO = new CustomSerialIO(); customIO.Deserialize(this); try { obj = objSurrogate.ConstructObject(customIO, objType); } catch (Exception e) { this.LogCustomDeserializationError(objId, objType, e); } } if (obj == null) { obj = objType.CreateInstanceOf(); } if (obj == null) { obj = objType.CreateInstanceOf(true); } } // Prepare object reference this.idManager.Inject(obj, objId); // Read custom object data if (custom) { CustomSerialIO customIO = new CustomSerialIO(); customIO.Deserialize(this); ISerializable objAsCustom; if (objSurrogate != null) { objSurrogate.RealObject = obj; objAsCustom = objSurrogate.SurrogateObject; } else { objAsCustom = obj as ISerializable; } if (objAsCustom != null) { try { objAsCustom.ReadData(customIO); } catch (Exception e) { this.LogCustomDeserializationError(objId, objType, e); } } else if (obj != null && objType != null) { this.SerializationLog.WriteWarning( "Object data (Id {0}) is flagged for custom deserialization, yet the objects Type ('{1}') does not support it. Guessing associated fields...", objId, Log.Type(objType)); this.SerializationLog.PushIndent(); foreach (var pair in customIO.Data) { this.AssignValueToField(objSerializeType, obj, pair.Key, pair.Value); } this.SerializationLog.PopIndent(); } } // Red non-custom object data else { // Determine data layout TypeDataLayout layout = this.ReadTypeDataLayout(objTypeString); // Read fields if (this.dataVersion <= 2) { for (int i = 0; i < layout.Fields.Length; i++) { object fieldValue = this.ReadObjectData(); this.AssignValueToField(objSerializeType, obj, layout.Fields[i].name, fieldValue); } } else if (this.dataVersion >= 3) { bool[] fieldOmitted = new bool[layout.Fields.Length]; this.ReadArrayData(fieldOmitted); for (int i = 0; i < layout.Fields.Length; i++) { if (fieldOmitted[i]) { continue; } object fieldValue = this.ReadObjectData(); this.AssignValueToField(objSerializeType, obj, layout.Fields[i].name, fieldValue); } } } return(obj); }
/// <summary> /// Reads a structural object, including referenced objects. /// </summary> /// <returns>The object that has been read.</returns> protected object ReadStruct() { // Read struct type string objTypeString = this.reader.GetAttribute("type"); string objIdString = this.reader.GetAttribute("id"); string customString = this.reader.GetAttribute("custom"); string surrogateString = this.reader.GetAttribute("surrogate"); uint objId = objIdString == null ? 0 : XmlConvert.ToUInt32(objIdString); bool custom = customString != null && XmlConvert.ToBoolean(customString); bool surrogate = surrogateString != null && XmlConvert.ToBoolean(surrogateString); Type objType = this.ResolveType(objTypeString, objId); SerializeType objSerializeType = null; if (objType != null) { objSerializeType = objType.GetSerializeType(); } // Retrieve surrogate if requested ISurrogate objSurrogate = null; if (surrogate && objType != null) { objSurrogate = this.GetSurrogateFor(objType); } // Construct object object obj = null; if (objType != null) { if (objSurrogate != null) { custom = true; // Set fake object reference for surrogate constructor: No self-references allowed here. this.idManager.Inject(null, objId); CustomSerialIO customIO = new CustomSerialIO(CustomSerialIO.HeaderElement); customIO.Deserialize(this); try { obj = objSurrogate.ConstructObject(customIO, objType); } catch (Exception e) { this.LogCustomDeserializationError(objId, objType, e); } } if (obj == null) { obj = objType.CreateInstanceOf(); } if (obj == null) { obj = objType.CreateInstanceOf(true); } } // Prepare object reference this.idManager.Inject(obj, objId); // Read custom object data if (custom) { CustomSerialIO customIO = new CustomSerialIO(CustomSerialIO.BodyElement); customIO.Deserialize(this); ISerializable objAsCustom; if (objSurrogate != null) { objSurrogate.RealObject = obj; objAsCustom = objSurrogate.SurrogateObject; } else { objAsCustom = obj as ISerializable; } if (objAsCustom != null) { try { objAsCustom.ReadData(customIO); } catch (Exception e) { this.LogCustomDeserializationError(objId, objType, e); } } else if (obj != null && objType != null) { this.SerializationLog.WriteWarning( "Object data (Id {0}) is flagged for custom deserialization, yet the objects Type ('{1}') does not support it. Guessing associated fields...", objId, Log.Type(objType)); this.SerializationLog.PushIndent(); foreach (var pair in customIO.Data) { this.AssignValueToField(objSerializeType, obj, pair.Key, pair.Value); } this.SerializationLog.PopIndent(); } } // Red non-custom object data else if (!this.reader.IsEmptyElement) { // Read fields bool scopeChanged; string fieldName; object fieldValue; while (true) { fieldValue = this.ReadObjectData(out fieldName, out scopeChanged); if (scopeChanged) { break; } this.AssignValueToField(objSerializeType, obj, fieldName, fieldValue); } } return(obj); }