Exemplo n.º 1
0
        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();
        }
Exemplo n.º 2
0
 /// <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;
 }
Exemplo n.º 3
0
 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);
        }
Exemplo n.º 8
0
        /// <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();
        }
Exemplo n.º 10
0
        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();
        }
Exemplo n.º 11
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);
        }