private void WriteXmlDictionary(object o, XmlWriter writer, TypeDefinition def, string name, bool forceSaveType) { writer.WriteStartElement(name ?? def.Name); if (forceSaveType) { writer.WriteAttributeString(Type, def.FullName); } var dict = o as IDictionary; if (dict != null) { foreach (DictionaryEntry item in dict) { writer.WriteStartElement(Item); var itemDef = TypeDefinitionCache.GetDefinition(item.Key.GetType()); WriteXml(writer, item.Key, itemDef, Key, forceSaveType: def.GenericArguments[0].FullName != itemDef.FullName); var itemValueDef = TypeDefinitionCache.GetDefinition(item.Value.GetType()); WriteXml(writer, item.Value, itemValueDef, Value, forceSaveType: def.GenericArguments[1].FullName != itemValueDef.FullName); writer.WriteEndElement(); } } writer.WriteEndElement(); }
/// <summary> /// Deserializes the XML document /// </summary> /// <param name="xml">The XML document</param> /// <param name="type">The type of returned object</param> /// <returns>deserialized object</returns> public object Deserialize(string xml, Type type) { var def = TypeDefinitionCache.GetDefinition(type); XDocument doc = XDocument.Parse(xml); var result = ReadXml(doc.Root, def); _referencesObjects.Clear(); return result; }
private TypeDefinition GetElementTypeDefinition(XElement element, Type defuaultType = null) { var typeAttribute = element.Attribute(Type); if (typeAttribute != null) { return TypeDefinitionCache.GetDefinition(TypeDefinitionCache.GetType(typeAttribute.Value)); } return defuaultType == null ? null : TypeDefinitionCache.GetDefinition(defuaultType); }
void WriteXmlArray(object o, XmlWriter writer, TypeDefinition def, string name, bool forceSaveType) { writer.WriteStartElement(name ?? def.Name); if (forceSaveType) { writer.WriteAttributeString(Type, def.FullName); } var toWriteReservedObject = new List <string>(); var elementType = ElementTypeLocator.Default.Locate(def.Type); if (elementType != null) { var enumerable = o as IEnumerable; if (enumerable != null) { var items = enumerable as Array ?? enumerable.Cast <object>().ToArray(); var conf = GetConfiguration(elementType); if (conf != null && conf.IsObjectReference) { foreach (var item in items) { var objectId = conf.GetObjectId(item); var key = item.GetType().FullName + Underscore + objectId; if (!_referencesObjects.ContainsKey(key) && !_reservedReferencesObjects.ContainsKey(key)) { toWriteReservedObject.Add(key); _reservedReferencesObjects.Add(key, item); } } } foreach (var item in items) { var itemDef = TypeDefinitionCache.GetDefinition(item.GetType()); var writeReservedObject = false; if (conf != null && conf.IsObjectReference) { var objectId = conf.GetObjectId(item); var key = item.GetType() + Underscore + objectId; if (toWriteReservedObject.Contains(key)) { writeReservedObject = true; } } WriteXml(writer, item, itemDef, writeReservedObject: writeReservedObject, forceSaveType: elementType.FullName != itemDef.FullName); } } } writer.WriteEndElement(); }
private void WriteXmlArray(object o, XmlWriter writer, TypeDefinition def, string name) { writer.WriteStartElement(name ?? def.Name); List <string> toWriteReservedObject = new List <string>(); var array = o as Array; var list = o as IEnumerable; if (array != null || list != null) { Type type; if (array != null) { type = def.Type.GetElementType(); } else { type = def.GenericArguments[0]; } var conf = GetConfiguration(type); if (conf != null && conf.IsObjectReference) { foreach (var item in array ?? list) { var objectId = conf.GetObjectId(item); var key = item.GetType().FullName + "_" + objectId; if (!_referencesObjects.ContainsKey(key) && !_reservedReferencesObjects.ContainsKey(key)) { toWriteReservedObject.Add(key); _reservedReferencesObjects.Add(key, item); } } } foreach (var item in array ?? list) { var itemDef = TypeDefinitionCache.GetDefinition(item.GetType()); var writeReservedObject = false; if (conf != null && conf.IsObjectReference) { var objectId = conf.GetObjectId(item); var key = item.GetType() + "_" + objectId; if (toWriteReservedObject.Contains(key)) { writeReservedObject = true; } } WriteXml(writer, item, itemDef, writeReservedObject: writeReservedObject); } } writer.WriteEndElement(); }
private object ReadXmlArray(XElement currentNode, TypeDefinition type, object instance = null) { int arrayCount = currentNode.Elements().Count(); var elements = currentNode.Elements().ToArray(); object list = null; Array array = null; if (type.IsArray) { array = (Array)instance ?? Array.CreateInstance(type.Type.GetElementType(), arrayCount); } else { list = instance ?? type.ObjectActivator(); } for (int i = 0; i < arrayCount; i++) { var element = elements[i]; TypeDefinition cd = null; var ta = element.Attribute("type"); if (ta != null) { var currentNodeType = TypeDefinitionCache.GetType(ta.Value); cd = TypeDefinitionCache.GetDefinition(currentNodeType); } if (type.IsArray) { if (cd == null) { cd = TypeDefinitionCache.GetDefinition(type.Type.GetElementType()); } array?.SetValue(ReadXml(element, cd), i); } else { if (cd == null) { cd = TypeDefinitionCache.GetDefinition(type.GenericArguments[0]); } type.MethodAddToCollection(list, ReadXml(element, cd)); } } if (type.IsArray) { return(array); } return(list); }
private object ReadXmlDictionary(XElement currentNode, TypeDefinition type, object instance = null) { int arrayCount = currentNode.Elements().Count(); var elements = currentNode.Elements().ToArray(); object dict = instance ?? type.ObjectActivator();; for (int i = 0; i < arrayCount; i++) { var element = elements[i]; TypeDefinition keyDef = null; TypeDefinition ValuDef = null; var key = element.Element("Key"); var value = element.Element("Value"); var keyTypeAttr = key.Attribute("type"); if (keyTypeAttr != null) { var nodeType = TypeDefinitionCache.GetType(keyTypeAttr.Value); keyDef = TypeDefinitionCache.GetDefinition(nodeType); } else { keyDef = TypeDefinitionCache.GetDefinition(type.GenericArguments[0]); } var valueTypeAttr = value.Attribute("type"); if (valueTypeAttr != null) { var nodeType = TypeDefinitionCache.GetType(valueTypeAttr.Value); ValuDef = TypeDefinitionCache.GetDefinition(nodeType); } else { ValuDef = TypeDefinitionCache.GetDefinition(type.GenericArguments[1]); } type.MethodAddToDictionary(dict, ReadXml(key, keyDef), ReadXml(value, ValuDef)); } return(dict); }
/// <summary> /// Serializes the specified <see cref="T:System.Object" /> and returns xml document in string /// </summary> /// <param name="o">The <see cref="T:System.Object" /> to serialize. </param> /// <returns>xml document in string</returns> public string Serialize(object o) { var def = TypeDefinitionCache.GetDefinition(o.GetType()); string xml; using (var ms = new MemoryStream()) { using (XmlWriter xw = XmlWriter.Create(ms)) { WriteXml(xw, o, def); } ms.Position = 0; using (var sr = new StreamReader(ms)) { xml = sr.ReadToEnd(); } } _referencesObjects.Clear(); return(xml); }
private void WriteXmlDictionary(object o, XmlWriter writer, TypeDefinition def, string name) { writer.WriteStartElement(name ?? def.Name); var dict = o as IDictionary; if (dict != null) { foreach (DictionaryEntry item in dict) { writer.WriteStartElement("Item"); var itemDef = TypeDefinitionCache.GetDefinition(item.Key.GetType()); WriteXml(writer, item.Key, itemDef, "Key"); var itemValueDef = TypeDefinitionCache.GetDefinition(item.Value.GetType()); WriteXml(writer, item.Value, itemValueDef, "Value"); writer.WriteEndElement(); } } writer.WriteEndElement(); }
private void WriteXml(XmlWriter writer, object o, TypeDefinition type, string name = null, bool writeReservedObject = false, bool forceSaveType = false) { if (type.IsPrimitive) { WriteXmlPrimitive(o, writer, type, name); return; } if (type.IsDictionary) { WriteXmlDictionary(o, writer, type, name, forceSaveType); return; } if (type.IsArray || type.IsEnumerable) { WriteXmlArray(o, writer, type, name, forceSaveType); return; } writer.WriteStartElement(name ?? type.Name); // Get configuration for type var configuration = GetConfiguration(type.Type); if (configuration != null) { if (configuration.IsObjectReference) { var objectId = configuration.GetObjectId(o); var key = type.FullName + Underscore + objectId; if (writeReservedObject && _reservedReferencesObjects.ContainsKey(key)) { _reservedReferencesObjects.Remove(key); } else if (_referencesObjects.ContainsKey(key) || _reservedReferencesObjects.ContainsKey(key)) { if (forceSaveType) { writer.WriteAttributeString(Type, type.FullName); } writer.WriteAttributeString(Ref, objectId); writer.WriteEndElement(); return; } writer.WriteAttributeString(Type, type.FullName); writer.WriteAttributeString(Id, objectId); _referencesObjects.Add(key, o); } else { writer.WriteAttributeString(Type, type.FullName); } if (configuration.Version > 0) { writer.WriteAttributeString(Version, configuration.Version.ToString(CultureInfo.InvariantCulture)); } if (configuration.IsCustomSerializer) { configuration.WriteObject(writer, o); writer.WriteEndElement(); return; } } else { writer.WriteAttributeString(Type, type.FullName); } var properties = type.Properties; foreach (var propertyInfo in properties) { var propertyValue = propertyInfo.GetValue(o); if (propertyValue == null) { continue; } var defType = TypeDefinitionCache.GetDefinition(propertyValue.GetType()); if (defType.IsObjectToSerialize || defType.IsArray || defType.IsEnumerable) { WriteXml(writer, propertyValue, defType, propertyInfo.Name, forceSaveType: propertyInfo.IsWritable && propertyInfo.TypeDefinition.FullName != defType.FullName); } else if (defType.IsEnum) { writer.WriteStartElement(propertyInfo.Name); writer.WriteString(propertyValue.ToString()); writer.WriteEndElement(); } else { bool toEncrypt = false; if (configuration != null) { if (configuration.CheckPropertyEncryption(propertyInfo.Name)) { toEncrypt = true; } } if (propertyInfo.TypeDefinition.Type.FullName != defType.Type.FullName) { WriteXmlPrimitive(propertyValue, writer, defType, propertyInfo.Name, toEncrypt, defType.Type.FullName); } else { WriteXmlPrimitive(propertyValue, writer, defType, propertyInfo.Name, toEncrypt); } } } writer.WriteEndElement(); }
private object ReadXml(XElement currentNode, TypeDefinition type, object instance = null) { if (type.IsPrimitive) { return(PrimitiveValueTools.GetPrimitiveValue(currentNode.Value, type, currentNode.Name.LocalName)); } if (type.IsDictionary) { return(ReadXmlDictionary(currentNode, type)); } if (type.IsArray || type.IsEnumerable) { return(ReadXmlArray(currentNode, type, instance)); } if (currentNode == null) { return(null); } // Retrieve type from XML (Property can be base type. In xml can be saved inherited object) or type of get property var currentNodeDef = GetElementTypeDefinition(currentNode) ?? type; // Get configuration for type var configuration = GetConfiguration(currentNodeDef.Type); if (configuration != null) { // Run migrator if exists if (configuration.Version > 0) { configuration.Map(currentNodeDef.Type, currentNode); } // run custom serializer if exists if (configuration.IsCustomSerializer) { return(configuration.ReadObject(currentNode)); } } // Create new instance if not exists var currentObject = instance ?? currentNodeDef.ObjectActivator(); if (configuration != null) { if (configuration.IsObjectReference) { string refId = currentNode.Attribute(Ref)?.Value; if (!string.IsNullOrEmpty(refId)) { var key = currentNodeDef.FullName + Underscore + refId; if (_referencesObjects.ContainsKey(key)) { return(_referencesObjects[key]); } _referencesObjects.Add(key, currentObject); } string objectId = currentNode.Attribute(Id)?.Value; if (!string.IsNullOrEmpty(objectId)) { var key = currentNodeDef.FullName + Underscore + objectId; if (_referencesObjects.ContainsKey(key)) { currentObject = _referencesObjects[key]; } else { _referencesObjects.Add(key, currentObject); } } } } // Read all elements foreach (var xElement in currentNode.Elements()) { var localName = xElement.Name.LocalName; var value = xElement.Value; var propertyInfo = type.GetProperty(localName); if (propertyInfo == null) { throw new InvalidOperationException("Missing property " + currentNode.Name.LocalName + "\\" + localName); } var propertyDef = propertyInfo.TypeDefinition; if (xElement.HasAttributes && xElement.Attribute(Type) != null) { // If type of property is saved in xml, we need check type of object actual assigned to property. There may be a base type. Type targetType = TypeDefinitionCache.GetType(xElement.Attribute(Type).Value); var targetTypeDef = TypeDefinitionCache.GetDefinition(targetType); var obj = propertyInfo.GetValue(currentObject); if ((obj == null || obj.GetType() != targetType) && targetTypeDef.ObjectActivator != null) { obj = targetTypeDef.ObjectActivator(); } var obj2 = ReadXml(xElement, targetTypeDef, obj); propertyInfo.SetValue(currentObject, obj2); } else if (propertyDef.IsObjectToSerialize || propertyDef.IsArray || propertyDef.IsEnumerable || propertyDef.IsDictionary) { //If xml does not contain type but we known that it is object var obj = propertyInfo.GetValue(currentObject); var obj2 = ReadXml(xElement, propertyDef, obj); if (obj == null && obj2 != null) { propertyInfo.SetValue(currentObject, obj2); } } else { if (string.IsNullOrEmpty(value)) { continue; } if (configuration != null) { if (configuration.CheckPropertyEncryption(propertyInfo.Name)) { var algorithm = GetEncryptionAlgorithm(); if (algorithm != null) { value = algorithm.Decrypt(value); } } } object primitive = PrimitiveValueTools.GetPrimitiveValue(value, propertyDef, xElement.Name.LocalName); propertyInfo.SetValue(currentObject, primitive); } } return(currentObject); }
private object ReadXml(XElement currentNode, TypeDefinition type, object instance = null) { if (type.IsPrimitive) { return(PrimitiveValueTools.GetPrimitiveValue(currentNode.Value, type, currentNode.Name.LocalName)); } if (type.IsDictionary) { return(ReadXmlDictionary(currentNode, type)); } if (type.IsArray || type.IsEnumerable) { return(ReadXmlArray(currentNode, type, instance)); } if (currentNode == null) { return(null); } // Retrieve type from XML (Property can be base type. In xml can be saved inherited object) or type of get property var currentNodeDef = GetElementTypeDefinition(currentNode) ?? type; // Get configuration for type var configuration = GetConfiguration(currentNodeDef.Type); //Console.Write($"{currentNodeDef.FullName} {currentNodeDef.Type} {configuration?.IsObjectReference}"); //Console.WriteLine(); if (configuration != null) { // Run migrator if exists if (configuration.Version > 0) { configuration.Map(currentNodeDef.Type, currentNode); } // run custom serializer if exists if (configuration.IsCustomSerializer) { return(configuration.ReadObject(currentNode)); } } //Console.Write($"{currentNodeDef.FullName} {currentNodeDef.Type} {configuration?.IsObjectReference}"); //Console.WriteLine(); // Create new instance if not exists var currentObject = instance ?? currentNodeDef.ObjectActivator(); //Console.Write($"1"); //Console.WriteLine(); if (configuration != null) { //Console.Write($"2"); //Console.WriteLine(); if (configuration.IsObjectReference) { string refId = currentNode.Attribute(Ref)?.Value; //Console.Write($"{refId}"); //Console.WriteLine(); if (!string.IsNullOrEmpty(refId)) { //Console.Write($"3"); //Console.WriteLine(); if (ExternalReferencesObjects.ContainsKey(currentNodeDef.FullName.Replace('.', '_') + Underscore + refId)) { //Console.Write($"4"); //Console.WriteLine(); //Console.Write($"{currentNodeDef.FullName.Replace('.', '_') + Underscore + refId}"); //Console.WriteLine(); //Console.Write($"{ExternalReferencesObjects[currentNodeDef.FullName.Replace('.', '_') + Underscore + refId]}"); //Console.WriteLine(); //if (currentNodeDef.FullName.Replace('.', '_') + Underscore + refId == "InSimu_NewEditor_Data_Symptoms_SymptomFamily_Hasmenes") // throw new Exception(); return(ExternalReferencesObjects[currentNodeDef.FullName.Replace('.', '_') + Underscore + refId]); } //Console.Write(currentNodeDef.FullName.Replace('.', '_') + Underscore + refId); //Console.WriteLine(); var key = currentNodeDef.FullName + Underscore + refId; if (_referencesObjects.ContainsKey(key)) { return(_referencesObjects[key]); } _referencesObjects.Add(key, currentObject); } string objectId = currentNode.Attribute(Id)?.Value; if (!string.IsNullOrEmpty(objectId)) { var key = currentNodeDef.FullName + Underscore + objectId; if (_referencesObjects.ContainsKey(key)) { currentObject = _referencesObjects[key]; } else { _referencesObjects.Add(key, currentObject); } } } } // Read all elements foreach (var xElement in currentNode.Elements()) { var localName = xElement.Name.LocalName; var value = xElement.Value; var propertyInfo = type.GetProperty(localName); if (propertyInfo == null) { throw new InvalidOperationException("Missing property " + currentNode.Name.LocalName + "\\" + localName); } var propertyDef = propertyInfo.TypeDefinition; if (xElement.HasAttributes && xElement.Attribute(Type) != null) { // If type of property is saved in xml, we need check type of object actual assigned to property. There may be a base type. Type targetType = TypeDefinitionCache.GetType(xElement.Attribute(Type).Value); var targetTypeDef = TypeDefinitionCache.GetDefinition(targetType); var obj = propertyInfo.GetValue(currentObject); if ((obj == null || obj.GetType() != targetType) && targetTypeDef.ObjectActivator != null) { obj = targetTypeDef.ObjectActivator(); } var obj2 = ReadXml(xElement, targetTypeDef, obj); propertyInfo.SetValue(currentObject, obj2); } else if (propertyDef.IsObjectToSerialize || propertyDef.IsArray || propertyDef.IsEnumerable || propertyDef.IsDictionary) { //If xml does not contain type but we known that it is object var obj = propertyInfo.GetValue(currentObject); var obj2 = ReadXml(xElement, propertyDef, obj); //Console.Write($"{obj} {obj2}"); //Console.WriteLine(); bool isObjValid = (obj != null); try { //HACK: This is how unitialized objects created as default property values are invalidated. It has caused major headaches. Touch with care and find a proper solution if possible! isObjValid = isObjValid && ((obj is ICollection) || !$"{obj}".StartsWith("<new")); isObjValid = isObjValid && ((obj is ICollection) || !$"{obj}".StartsWith("<empty")); } catch { isObjValid = false; } if ((!isObjValid || propertyDef.IsDictionary) && obj2 != null) { //Console.Write($"***"); //Console.WriteLine(); propertyInfo.SetValue(currentObject, obj2); } } else { if (string.IsNullOrEmpty(value)) { continue; } if (configuration != null) { if (configuration.CheckPropertyEncryption(propertyInfo.Name)) { var algorithm = GetEncryptionAlgorithm(); if (algorithm != null) { value = algorithm.Decrypt(value); } } } object primitive = PrimitiveValueTools.GetPrimitiveValue(value, propertyDef, xElement.Name.LocalName); propertyInfo.SetValue(currentObject, primitive); } } return(currentObject); }