public void WriteFromObject(object obj, List <SerializerError> errors, XMLSerializerParams parameters) { targetType.GetAllFields(_fields); foreach (var fieldData in _fields) { if (!fieldData.isSerialized) { continue; } string fieldName = fieldData.fieldInfo.Name; XElement targetElement = new XElement(fieldName); xElement.Add(targetElement); var fieldObj = fieldData.fieldInfo.GetValue(obj); if (fieldObj == null) // Null special case { if (!fieldData.fieldInfo.GetCustomAttributes(true).Any((attrib) => attrib is AlwaysSerializedAttribute)) { return; } targetElement.Value = XMLSerializer.TokenNull; continue; } var fieldObjType = SerializerCache.GetSerializableTypeCacheFor(fieldObj.GetType()); bool isCollection = SerializedCollectionData.IsCollection(fieldData.fieldInfo.FieldType); IXMLDataSerializer serializer = SerializerCache.GetBestSerializerFor(fieldData.fieldInfo.FieldType); if (!ReferenceEquals(serializer, null)) { try { if (!SerializerValidation.SerializerWasFound(parameters, targetElement, serializer, fieldName, fieldObjType == null ? null : fieldObjType.type, fieldObjType == null ? null : fieldObjType.type, "SERIALIZE", errors)) { continue; } serializer.Serialize(fieldObj, targetElement, parameters); } catch (Exception ex) { errors.Add(new SerializerError(SerializerErrorSeverity.ERROR, "SERIALIZE", -1, "Serializer threw exception on field " + fieldName + " on type " + fieldObjType.type + ":\n\n" + ex.ToString() + "\n\nSkipping field!")); } } else if (isCollection) { var col = new SerializedCollectionData(fieldData.fieldInfo.FieldType, targetElement); col.WriteFromObject(fieldObj, targetElement, errors, parameters); } else { // root reference? if (fieldData.isSerializableRoot) { targetElement.Value = (fieldObj as ISerializableRoot).identifier; } else { // Determine which type to serialize string typeName = fieldObjType.type.Name; // Write class attribute if (!ReferenceEquals(fieldData.fieldInfo.FieldType, fieldObjType.type)) { targetElement.SetAttributeValue(XMLSerializer.AttributeType, typeName); } // Field not serializable? if (!SerializerValidation.DataFieldSerializerValid(parameters, targetElement, fieldObjType, typeName, fieldName, "SERIALIZE", errors)) { continue; } // Write field var d = new SerializedData(fieldObjType, targetElement); d.WriteFromObject(fieldObj, errors, parameters); } } } }
/// <summary> /// It will for every field with string data deserialize this data using <see cref="IXMLDataSerializer"/>. /// /// For every sub-data field a <see cref="SerializedData"/> object is being written to <see cref="fields"/>. /// </summary> /// <param name="filename">Only used for error reporting</param> public void LoadFieldsFromXML(string filename, List <SerializerError> errors, XMLSerializerParams parameters) { foreach (var xNode in xElement.Nodes()) { if (!SerializerValidation.NodeIsElement(parameters, xNode, filename, errors)) // Malformed XML { continue; } var xElement = xNode as XElement; var elementName = xElement.Name.LocalName; // Field unknown? if (!SerializerValidation.FieldKnown(parameters, xElement, targetType, elementName, filename, errors)) { continue; } debug.Add(elementName, xElement); var _fieldData = targetType.GetFieldData(elementName); var fieldData = _fieldData.Value; var fieldType = fieldData.serializableTypeCache; if (xElement.Value == XMLSerializer.TokenNull) // Null special case { fields.Add(elementName, null); continue; } bool isCollection = SerializedCollectionData.IsCollection(fieldData.fieldInfo.FieldType); IXMLDataSerializer serializer = SerializerCache.GetBestSerializerFor(fieldData.fieldInfo.FieldType); if (!ReferenceEquals(serializer, null)) { try { if (!SerializerValidation.SerializerWasFound(parameters, xElement, serializer, elementName, targetType == null ? null : targetType.type, fieldType == null ? null : fieldType.type, filename, errors)) { continue; } fields.Add(elementName, serializer.Deserialize(fieldData.fieldInfo.FieldType, xElement, parameters)); } catch (Exception ex) { errors.Add(new SerializerError(SerializerErrorSeverity.ERROR, filename, -1, "Serializer threw exception on field " + elementName + " on type " + targetType.type + ":\n\n" + ex.ToString() + "\n\nSkipping field!")); } } else if (isCollection) { var col = new SerializedCollectionData(fieldData.fieldInfo.FieldType, xElement); col.ParseAndLoadData(filename, errors, parameters); fields.Add(elementName, col); // Collection override action? var collectionOverrideAttrib = xElement.Attribute(XMLSerializer.AttributeCollectionOverrideAction); if (!ReferenceEquals(collectionOverrideAttrib, null)) { collectionOverrideActions.Set(elementName, (CollectionOverrideAction)Enum.Parse(typeof(CollectionOverrideAction), collectionOverrideAttrib.Value)); } } else { // root reference? if (fieldData.isSerializableRoot) { fields.Add(elementName, new SerializedRootObjectReference() { identifier = xElement.Value as string }); } else { // Determine which type to serialize var targetType = fieldData.serializableTypeCache; string typeName = fieldData.fieldInfo.Name; // Check if element explicitly overwrites the type to support polymorphism // The field type might be some base class type and the xml overwrites this type with a class extending from the base var classAttrib = xElement.Attribute(XMLSerializer.AttributeType); if (!ReferenceEquals(classAttrib, null)) { targetType = SerializerCache.GetSerializableTypeCacheFor(classAttrib.Value, parameters.standardNamespace); typeName = classAttrib.Value; } // Field not serializable? if (!SerializerValidation.DataFieldSerializerValid(parameters, xElement, targetType, typeName, elementName, filename, errors)) { continue; } // Resolve field name type var d = new SerializedData(targetType, xElement as XElement); d.LoadFieldsFromXML(filename, errors, parameters); fields.Add(elementName, d); } } } }