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); }
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); }
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); }