Ejemplo n.º 1
0
        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);
        }