/// <summary> /// Creates a new SerializeType based on a <see cref="System.Type"/>, gathering all the information that is necessary for serialization. /// </summary> /// <param name="t"></param> public SerializeType(Type t) { this.type = t.GetTypeInfo(); this.typeString = t.GetTypeId(); this.dataType = GetDataType(this.type); this.dontSerialize = this.type.HasAttributeCached <DontSerializeAttribute>(); this.defaultValue = this.type.GetDefaultOf(); this.surrogate = Serializer.GetSurrogateFor(this.type); if (this.dataType == DataType.Struct && this.surrogate == null) { // Retrieve all fields that are not flagged not to be serialized List <FieldInfo> filteredFields = this.type .DeclaredFieldsDeep() .Where(f => !f.IsStatic && !f.HasAttributeCached <DontSerializeAttribute>()) .ToList(); // Hack: Remove some specific fields based on an internal blacklist this.RemoveBlacklistedFields(filteredFields); // Store the filtered fields in a fixed form this.fields = filteredFields.ToArray(); this.fields.StableSort((a, b) => string.Compare(a.Name, b.Name)); } else { this.fields = new FieldInfo[0]; } }
private void WriteStruct(object obj, ObjectHeader header) { ISerializeExplicit objAsCustom = obj as ISerializeExplicit; ISerializeSurrogate objSurrogate = GetSurrogateFor(header.ObjectType); this.writer.Write(objAsCustom != null); this.writer.Write(objSurrogate != null); if (objSurrogate != null) { objSurrogate.RealObject = obj; objAsCustom = objSurrogate.SurrogateObject; CustomSerialIO customIO = new CustomSerialIO(); try { objSurrogate.WriteConstructorData(customIO); } catch (Exception e) { this.LogCustomSerializationError(header.ObjectId, header.ObjectType, e); } customIO.Serialize(this); } if (objAsCustom != null) { CustomSerialIO customIO = new CustomSerialIO(); try { objAsCustom.WriteData(customIO); } catch (Exception e) { this.LogCustomSerializationError(header.ObjectId, header.ObjectType, e); } customIO.Serialize(this); } else { // Assure the type data layout has been written (only once per file) this.WriteTypeDataLayout(header.SerializeType); // If we're serializing a value type, skip the entire object body if // it equals the zero-init struct. This will keep struct-heavy data a lot // smaller binary-wise. bool skipEntireBody = header.ObjectType.IsValueType && object.Equals(obj, header.SerializeType.DefaultValue); // Write omitted field bitmask bool[] fieldOmitted = new bool[header.SerializeType.Fields.Length]; for (int i = 0; i < fieldOmitted.Length; i++) { fieldOmitted[i] = skipEntireBody || this.IsFieldBlocked(header.SerializeType.Fields[i], obj); } this.WriteArrayData(fieldOmitted); // Write the structs fields for (int i = 0; i < header.SerializeType.Fields.Length; i++) { if (fieldOmitted[i]) { continue; } this.WriteObjectData(header.SerializeType.Fields[i].GetValue(obj)); } } }
private void WriteStruct(XElement element, object obj, ObjectHeader header) { ISerializeExplicit objAsCustom = obj as ISerializeExplicit; ISerializeSurrogate objSurrogate = GetSurrogateFor(header.ObjectType); // Write the structs data type if (objAsCustom != null) { element.SetAttributeValue("custom", XmlConvert.ToString(true)); } if (objSurrogate != null) { element.SetAttributeValue("surrogate", XmlConvert.ToString(true)); } if (objSurrogate != null) { objSurrogate.RealObject = obj; objAsCustom = objSurrogate.SurrogateObject; CustomSerialIO customIO = new CustomSerialIO(); try { objSurrogate.WriteConstructorData(customIO); } catch (Exception e) { this.LogCustomSerializationError(header.ObjectId, header.ObjectType, e); } XElement customHeaderElement = new XElement(CustomSerialIO.HeaderElement); element.Add(customHeaderElement); customIO.Serialize(this, customHeaderElement); } if (objAsCustom != null) { CustomSerialIO customIO = new CustomSerialIO(); try { objAsCustom.WriteData(customIO); } catch (Exception e) { this.LogCustomSerializationError(header.ObjectId, header.ObjectType, e); } XElement customBodyElement = new XElement(CustomSerialIO.BodyElement); element.Add(customBodyElement); customIO.Serialize(this, customBodyElement); } else { // Write the structs fields foreach (FieldInfo field in header.SerializeType.Fields) { if (this.IsFieldBlocked(field, obj)) { continue; } XElement fieldElement = new XElement(GetXmlElementName(field.Name)); element.Add(fieldElement); this.WriteObjectData(fieldElement, field.GetValue(obj)); } } }
private void WriteStruct(object obj, ObjectHeader header) { ISerializeExplicit objAsCustom = obj as ISerializeExplicit; ISerializeSurrogate objSurrogate = GetSurrogateFor(header.ObjectType); this.writer.Write(objAsCustom != null); this.writer.Write(objSurrogate != null); if (objSurrogate != null) { objSurrogate.RealObject = obj; objAsCustom = objSurrogate.SurrogateObject; CustomSerialIO customIO = new CustomSerialIO(); try { objSurrogate.WriteConstructorData(customIO); } catch (Exception e) { this.LogCustomSerializationError(header.ObjectId, header.ObjectType, e); } customIO.Serialize(this); } if (objAsCustom != null) { CustomSerialIO customIO = new CustomSerialIO(); try { objAsCustom.WriteData(customIO); } catch (Exception e) { this.LogCustomSerializationError(header.ObjectId, header.ObjectType, e); } customIO.Serialize(this); } else { // Assure the type data layout has been written (only once per file) this.WriteTypeDataLayout(header.SerializeType); // Write omitted field bitmask bool[] fieldOmitted = new bool[header.SerializeType.Fields.Length]; for (int i = 0; i < fieldOmitted.Length; i++) { fieldOmitted[i] = this.IsFieldBlocked(header.SerializeType.Fields[i], obj); } this.WriteArrayData(fieldOmitted); // Write the structs fields for (int i = 0; i < header.SerializeType.Fields.Length; i++) { if (fieldOmitted[i]) { continue; } this.WriteObjectData(header.SerializeType.Fields[i].GetValue(obj)); } } }
private object ReadStruct(XElement element, ObjectHeader header) { // Read struct type string customString = element.GetAttributeValue("custom"); string surrogateString = element.GetAttributeValue("surrogate"); bool custom = customString != null && XmlConvert.ToBoolean(customString); bool surrogate = surrogateString != null && XmlConvert.ToBoolean(surrogateString); // Retrieve surrogate if requested ISerializeSurrogate objSurrogate = null; if (surrogate && header.ObjectType != null) { objSurrogate = GetSurrogateFor(header.ObjectType); } // Construct object object obj = null; if (header.ObjectType != null) { if (objSurrogate != null) { custom = true; // Set fake object reference for surrogate constructor: No self-references allowed here. this.idManager.Inject(null, header.ObjectId); CustomSerialIO customIO = new CustomSerialIO(); XElement customHeaderElement = element.Element(CustomSerialIO.HeaderElement) ?? element.Elements().FirstOrDefault(); if (customHeaderElement != null) { customIO.Deserialize(this, customHeaderElement); } try { obj = objSurrogate.ConstructObject(customIO, header.ObjectType); } catch (Exception e) { this.LogCustomDeserializationError(header.ObjectId, header.ObjectType, e); } } if (obj == null) { obj = header.ObjectType.CreateInstanceOf(); } } // Prepare object reference this.idManager.Inject(obj, header.ObjectId); // Read custom object data if (custom) { CustomSerialIO customIO = new CustomSerialIO(); XElement customBodyElement = element.Element(CustomSerialIO.BodyElement) ?? element.Elements().ElementAtOrDefault(1); if (customBodyElement != null) { customIO.Deserialize(this, customBodyElement); } ISerializeExplicit objAsCustom; if (objSurrogate != null) { objSurrogate.RealObject = obj; objAsCustom = objSurrogate.SurrogateObject; } else { objAsCustom = obj as ISerializeExplicit; } if (objAsCustom != null) { try { objAsCustom.ReadData(customIO); } catch (Exception e) { this.LogCustomDeserializationError(header.ObjectId, header.ObjectType, e); } } else if (obj != null && header.ObjectType != null) { this.LocalLog.WriteWarning( "Object data (Id {0}) is flagged for custom deserialization, yet the objects Type ('{1}') does not support it. Guessing associated fields...", header.ObjectId, Log.Type(header.ObjectType)); this.LocalLog.PushIndent(); foreach (var pair in customIO.Data) { this.AssignValueToField(header.SerializeType, obj, pair.Key, pair.Value); } this.LocalLog.PopIndent(); } } // Red non-custom object data else if (!element.IsEmpty) { // Read fields object fieldValue; foreach (XElement fieldElement in element.Elements()) { fieldValue = this.ReadObjectData(fieldElement); this.AssignValueToField(header.SerializeType, obj, GetCodeElementName(fieldElement.Name.LocalName), fieldValue); } } return(obj); }
private void WriteStruct(XElement element, object obj, ObjectHeader header) { ISerializeExplicit objAsCustom = obj as ISerializeExplicit; ISerializeSurrogate objSurrogate = GetSurrogateFor(header.ObjectType); // If we're serializing a value type, skip the entire object body if // it equals the zero-init struct. This will keep struct-heavy data a lot // more concise. if (header.ObjectType.IsValueType && object.Equals(obj, header.SerializeType.DefaultValue)) { return; } // Write information about custom or surrogate serialization if (objAsCustom != null) { element.SetAttributeValue("custom", XmlConvert.ToString(true)); } if (objSurrogate != null) { element.SetAttributeValue("surrogate", XmlConvert.ToString(true)); } if (objSurrogate != null) { objSurrogate.RealObject = obj; objAsCustom = objSurrogate.SurrogateObject; CustomSerialIO customIO = new CustomSerialIO(); try { objSurrogate.WriteConstructorData(customIO); } catch (Exception e) { this.LogCustomSerializationError(header.ObjectId, header.ObjectType, e); } XElement customHeaderElement = new XElement(CustomSerialIO.HeaderElement); element.Add(customHeaderElement); customIO.Serialize(this, customHeaderElement); } if (objAsCustom != null) { CustomSerialIO customIO = new CustomSerialIO(); try { objAsCustom.WriteData(customIO); } catch (Exception e) { this.LogCustomSerializationError(header.ObjectId, header.ObjectType, e); } XElement customBodyElement = new XElement(CustomSerialIO.BodyElement); element.Add(customBodyElement); customIO.Serialize(this, customBodyElement); } else { // Write the structs fields foreach (FieldInfo field in header.SerializeType.Fields) { if (this.IsFieldBlocked(field, obj)) { continue; } XElement fieldElement = new XElement(GetXmlElementName(field.Name)); element.Add(fieldElement); this.WriteObjectData(fieldElement, field.GetValue(obj)); } } }
private object ReadStruct(ObjectHeader header) { // Read struct type bool custom = this.reader.ReadBoolean(); bool surrogate = this.reader.ReadBoolean(); // Retrieve surrogate if requested ISerializeSurrogate objSurrogate = null; if (surrogate && header.ObjectType != null) { objSurrogate = GetSurrogateFor(header.ObjectType); } // Construct object object obj = null; if (header.ObjectType != null) { if (objSurrogate != null) { custom = true; // Set fake object reference for surrogate constructor: No self-references allowed here. this.idManager.Inject(null, header.ObjectId); CustomSerialIO customIO = new CustomSerialIO(); customIO.Deserialize(this); try { obj = objSurrogate.ConstructObject(customIO, header.ObjectType); } catch (Exception e) { this.LogCustomDeserializationError(header.ObjectId, header.ObjectType, e); } } if (obj == null) { obj = header.ObjectType.CreateInstanceOf(); } } // Prepare object reference this.idManager.Inject(obj, header.ObjectId); // Read custom object data if (custom) { CustomSerialIO customIO = new CustomSerialIO(); customIO.Deserialize(this); ISerializeExplicit objAsCustom; if (objSurrogate != null) { objSurrogate.RealObject = obj; objAsCustom = objSurrogate.SurrogateObject; } else { objAsCustom = obj as ISerializeExplicit; } if (objAsCustom != null) { try { objAsCustom.ReadData(customIO); } catch (Exception e) { this.LogCustomDeserializationError(header.ObjectId, header.ObjectType, e); } } else if (obj != null && header.ObjectType != null) { this.LocalLog.WriteWarning( "Object data (Id {0}) is flagged for custom deserialization, yet the objects Type ('{1}') does not support it. Guessing associated fields...", header.ObjectId, Log.Type(header.ObjectType)); this.LocalLog.PushIndent(); foreach (var pair in customIO.Data) { this.AssignValueToField(header.SerializeType, obj, pair.Key, pair.Value); } this.LocalLog.PopIndent(); } } // Red non-custom object data else { // Determine data layout TypeDataLayout layout = this.ReadTypeDataLayout(header.TypeString); // Read fields 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(header.SerializeType, obj, layout.Fields[i].name, fieldValue); } } return(obj); }