From ad3f01adedeb3f59ec01fdf8f67d0752891fdd41 Mon Sep 17 00:00:00 2001 From: Flamefire Date: Fri, 24 Oct 2014 22:48:47 +0200 Subject: [PATCH] Refactoring and fixes for some special cases (mostly lists) --- Vocaluxe/Base/CCover.cs | 9 +- VocaluxeLib/Structs.cs | 4 +- VocaluxeLib/Xml/CMyXmlDeserializer.cs | 155 +++++++++++++++----------- 3 files changed, 102 insertions(+), 66 deletions(-) diff --git a/Vocaluxe/Base/CCover.cs b/Vocaluxe/Base/CCover.cs index 3c1aee24..f40f64c9 100644 --- a/Vocaluxe/Base/CCover.cs +++ b/Vocaluxe/Base/CCover.cs @@ -23,6 +23,7 @@ using System.Threading; using System.Threading.Tasks; using VocaluxeLib; using VocaluxeLib.Draw; +using VocaluxeLib.Menu; using VocaluxeLib.Songs; using VocaluxeLib.Xml; @@ -168,10 +169,14 @@ namespace Vocaluxe.Base private static void _TestNewLoad(string path) { - SThemeCover theme; + /*SThemeCover theme; using (var stream = new FileStream(path, FileMode.Open)) theme = CMyXmlDeserializer.Deserialize(stream); - string cover = theme.Info.Author; + string cover = theme.Info.Author;*/ + STheme themescreen; + using (var stream = new FileStream(@"C:\Users\Alex\Documents\Vocaluxe\Output\Themes\Ambient\Screens\ScreenMain.xml", FileMode.Open)) + themescreen = CMyXmlDeserializer.Deserialize(stream); + string foo = themescreen.Informations.ScreenName; } /// diff --git a/VocaluxeLib/Structs.cs b/VocaluxeLib/Structs.cs index 929f76bd..6b9b0828 100644 --- a/VocaluxeLib/Structs.cs +++ b/VocaluxeLib/Structs.cs @@ -119,7 +119,7 @@ namespace VocaluxeLib [XmlRoot("Color")] public struct SThemeColor { - [DefaultValue(null), XmlAttribute] public string Name; + [DefaultValue(null), XmlAttribute] public string Name; public float? R; public float? G; public float? B; @@ -237,7 +237,7 @@ namespace VocaluxeLib [XmlRoot("Reflection")] public struct SReflection { - [XmlAttribute(AttributeName = "Enabled")] public bool Enabled; + [XmlAttribute] public bool Enabled; public float Height; public float Space; diff --git a/VocaluxeLib/Xml/CMyXmlDeserializer.cs b/VocaluxeLib/Xml/CMyXmlDeserializer.cs index 46ab10e2..4b2437e7 100644 --- a/VocaluxeLib/Xml/CMyXmlDeserializer.cs +++ b/VocaluxeLib/Xml/CMyXmlDeserializer.cs @@ -18,7 +18,8 @@ namespace VocaluxeLib.Xml { public string Name; public FieldInfo Info; - public bool IsList; + public bool IsList; //List with child elements () + public bool IsEmbeddedList; //List w/o child elements() public bool IsNullable; public Type SubType; } @@ -95,7 +96,13 @@ namespace VocaluxeLib.Xml if (field.FieldType.IsGenericType) { if (field.FieldType.GetGenericTypeDefinition() == typeof(List<>)) - info.IsList = true; + { + attElement = field.GetCustomAttributes(typeof(XmlArrayAttribute), false); + if (attElement.Length > 0) + info.IsList = true; + else + info.IsEmbeddedList = true; + } else if (field.FieldType.GetGenericTypeDefinition() == typeof(Nullable<>)) info.IsNullable = true; info.SubType = field.FieldType.GetGenericArguments()[0]; @@ -105,6 +112,18 @@ namespace VocaluxeLib.Xml return result; } + private static string _GetTypeName(Type type) + { + object[] att = type.GetCustomAttributes(typeof(XmlTypeAttribute), false); + if (att.Length > 0) + { + string name = ((XmlTypeAttribute)att[0]).TypeName; + if (!string.IsNullOrEmpty(name)) + return name; + } + return type.Name; + } + public static T Deserialize(Stream stream) where T : new() { return Deserialize(new XmlTextReader(stream) @@ -117,60 +136,61 @@ namespace VocaluxeLib.Xml private static object _GetValue(XmlNode node, Type type) { - object value; if (type.IsEnum) { string stringValue = node.InnerText; try { - value = Enum.Parse(type, stringValue); + return Enum.Parse(type, stringValue); } catch (Exception) { throw new XmlException("Invalid value in " + _FindXPath(node)); } } - else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) + if (type == typeof(string)) + return node.InnerText; + if (type.IsPrimitive) + return _GetPrimitiveValue(node, type); + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) { Type subType = type.GetGenericArguments()[0]; - value = Activator.CreateInstance(type); - MethodInfo addMethod = value.GetType().GetMethod("Add"); - List subValues = new List(node.ChildNodes.Count); + String subName = _GetTypeName(subType); + List subValues = new List(); foreach (XmlNode subNode in node.ChildNodes) { if (subNode is XmlComment) continue; + if (subName != subNode.Name) + throw new XmlException("Invalid list entry '" + subNode.Name + "' in " + _FindXPath(node) + "; Expected: " + subName); object subValue = _GetValue(subNode, subType); _ProcessChildNodes(subNode, ref subValue, true); subValues.Add(subValue); } - addMethod.Invoke(value, subValues.ToArray()); + return _CreateList(type, subValues); } - else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { Type subType = type.GetGenericArguments()[0]; - string stringValue = node.InnerText; - value = Convert.ChangeType(stringValue, subType); + return _GetPrimitiveValue(node, subType); } - else if (type == typeof(string)) - value = node.InnerText; - else if (!type.IsPrimitive) + + object value = Activator.CreateInstance(type); + _ProcessChildNodes(node, ref value, true); + _ProcessChildNodes(node, ref value, false); + return value; + } + + private static object _GetPrimitiveValue(XmlNode node, Type type) + { + object value; + try { - value = Activator.CreateInstance(type); - _ProcessChildNodes(node, ref value, true); - _ProcessChildNodes(node, ref value, false); + value = Convert.ChangeType(node.InnerText, type, CultureInfo.InvariantCulture); } - else + catch (FormatException) { - string stringValue = node.InnerText; - try - { - value = Convert.ChangeType(stringValue, type, CultureInfo.InvariantCulture); - } - catch (FormatException) - { - throw new XmlException("Invalid format in " + _FindXPath(node)); - } + throw new XmlException("Invalid format in " + _FindXPath(node) + ": '" + node.InnerText + "'"); } return value; } @@ -184,6 +204,23 @@ namespace VocaluxeLib.Xml return true; } + private static object _CreateList(Type type, List values) + { + object list = Activator.CreateInstance(type, new object[] {values.Count}); + if (values.Count > 0) + { + MethodInfo addMethod = type.GetMethod("Add"); + foreach (object value in values) + addMethod.Invoke(list, new object[] {value}); + } + return list; + } + + private static void _AddList(object result, SFieldInfo listField, List list) + { + listField.Info.SetValue(result, _CreateList(listField.Info.FieldType, list)); + } + private static void _ProcessChildNodes(XmlNode parent, ref object result, bool attributes) { IEnumerable nodes; @@ -210,56 +247,50 @@ namespace VocaluxeLib.Xml if (node.Name != curListName) { // End an embedded List - object list = Activator.CreateInstance(curListField.Info.FieldType); - MethodInfo addMethod = curListField.Info.FieldType.GetMethod("Add"); - addMethod.Invoke(list, subValues.ToArray()); - curListField.Info.SetValue(result, list); + _AddList(result, curListField, subValues); curField++; curListName = null; } + else + { + // Continue an embedded List + object subValue = _GetValue(node, curListField.SubType); + subValues.Add(subValue); + continue; + } } SFieldInfo field = new SFieldInfo(); - if (curListName == null) + for (; curField < fields.Count; curField++) { - for (; curField < fields.Count; curField++) - { - field = fields[curField]; - if (field.Name == node.Name) - break; - if (!_CheckAndSetDefaultValue(ref result, field)) - throw new XmlException("Unexpected element: " + _FindXPath(node) + "; Expected: " + field.Name); - } - if (curField >= fields.Count) - throw new XmlException("Unexpected element: " + _FindXPath(node)); - - if (field.IsList) - { - // Start an embedded List - curListField = field; - curListName = field.Name; - subValues.Clear(); - } + field = fields[curField]; + if (field.Name == node.Name) + break; + if (!_CheckAndSetDefaultValue(ref result, field)) + throw new XmlException("Unexpected element: " + _FindXPath(node) + "; Expected: " + field.Name); } - if (curListName == null) + if (curField >= fields.Count) + throw new XmlException("Unexpected element: " + _FindXPath(node)); + + if (field.IsEmbeddedList) + { + // Start an embedded List + curListField = field; + curListName = field.Name; + subValues.Clear(); + object subValue = _GetValue(node, curListField.SubType); + subValues.Add(subValue); + } + else { object value = _GetValue(node, field.Info.FieldType); field.Info.SetValue(result, value); curField++; } - else - { - // Continue an embedded List - object value = _GetValue(node, field.SubType); - subValues.Add(value); - } } if (curListName != null) { // End an embedded List - object list = Activator.CreateInstance(curListField.Info.FieldType); - MethodInfo addMethod = curListField.Info.FieldType.GetMethod("Add"); - addMethod.Invoke(list, subValues.ToArray()); - curListField.Info.SetValue(result, list); + _AddList(result, curListField, subValues); curField++; } }