From b044efe50edb99257bef7138e5d0283cbbdb8abf Mon Sep 17 00:00:00 2001 From: Flamefire Date: Fri, 24 Oct 2014 23:46:45 +0200 Subject: [PATCH] Add normalized attribute Allow empty embedded lists --- Vocaluxe/Base/CCover.cs | 17 +++++-- VocaluxeLib/Structs.cs | 9 ++-- VocaluxeLib/Xml/CMyXmlDeserializer.cs | 68 +++++++++++++++++++++------ 3 files changed, 71 insertions(+), 23 deletions(-) diff --git a/Vocaluxe/Base/CCover.cs b/Vocaluxe/Base/CCover.cs index f40f64c9..c3654484 100644 --- a/Vocaluxe/Base/CCover.cs +++ b/Vocaluxe/Base/CCover.cs @@ -21,6 +21,7 @@ using System.Drawing; using System.IO; using System.Threading; using System.Threading.Tasks; +using System.Xml.Serialization; using VocaluxeLib; using VocaluxeLib.Draw; using VocaluxeLib.Menu; @@ -167,16 +168,24 @@ namespace Vocaluxe.Base return new SThemeCover(); } + private static void Foo(STheme a, STheme b) + { + a = b; + } + 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)) + using (var stream = new StreamReader(Path.Combine(CBase.Themes.GetThemeScreensPath(-1), "ScreenMain.xml"))) themescreen = CMyXmlDeserializer.Deserialize(stream); - string foo = themescreen.Informations.ScreenName; + TextReader textReader = new StreamReader(Path.Combine(CBase.Themes.GetThemeScreensPath(-1), "ScreenMain.xml")); + XmlSerializer deserializer = new XmlSerializer(typeof(STheme)); + STheme theme2 = (STheme)deserializer.Deserialize(textReader); + Foo(theme2, themescreen); } /// diff --git a/VocaluxeLib/Structs.cs b/VocaluxeLib/Structs.cs index db67c872..364669f5 100644 --- a/VocaluxeLib/Structs.cs +++ b/VocaluxeLib/Structs.cs @@ -24,6 +24,7 @@ using System.Drawing; using System.Windows.Forms; using System.Xml.Serialization; using VocaluxeLib.Songs; +using VocaluxeLib.Xml; namespace VocaluxeLib { @@ -120,10 +121,10 @@ namespace VocaluxeLib public struct SThemeColor { [DefaultValue(null), XmlAttribute] public string Name; - public float? R; - public float? G; - public float? B; - public float? A; + [XmlNormalized] public float? R; + [XmlNormalized] public float? G; + [XmlNormalized] public float? B; + [XmlNormalized] public float? A; //Needed for serialization public bool NameSpecified diff --git a/VocaluxeLib/Xml/CMyXmlDeserializer.cs b/VocaluxeLib/Xml/CMyXmlDeserializer.cs index f46c69c7..ccf2e6bd 100644 --- a/VocaluxeLib/Xml/CMyXmlDeserializer.cs +++ b/VocaluxeLib/Xml/CMyXmlDeserializer.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -12,16 +13,22 @@ using System.Xml.Serialization; namespace VocaluxeLib.Xml { + // ReSharper disable InconsistentNaming + [AttributeUsage(AttributeTargets.Field)] + public class XmlNormalizedAttribute : Attribute {} + + // ReSharper restore InconsistentNaming + public static class CMyXmlDeserializer { private struct SFieldInfo { public string Name; public FieldInfo Info; - public FieldInfo SpecifiedField; public bool IsList; //List with child elements () public bool IsEmbeddedList; //List w/o child elements() public bool IsNullable; + public bool IsNormalized; public Type SubType; } @@ -72,13 +79,18 @@ namespace VocaluxeLib.Xml } #endregion Debug Helpers + private static bool _HasAttribute(this FieldInfo field, Type attributeType) + { + return field.GetCustomAttributes(attributeType, false).Length > 0; + } + private static List _GetFields(Type type, bool attributes) { List result = new List(); FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo field in fields) { - if (field.GetCustomAttributes(typeof(XmlIgnoreAttribute), false).Length > 0) + if (field._HasAttribute(typeof(XmlIgnoreAttribute))) continue; object[] attElement = field.GetCustomAttributes(typeof(XmlAttributeAttribute), false); if (attElement.Length > 0 != attributes) @@ -108,6 +120,11 @@ namespace VocaluxeLib.Xml info.IsNullable = true; info.SubType = field.FieldType.GetGenericArguments()[0]; } + if (field._HasAttribute(typeof(XmlNormalizedAttribute))) + { + Debug.Assert(field.FieldType == typeof(float) || (info.IsNullable && info.SubType == typeof(float)), "Only floats can be normalized"); + info.IsNormalized = true; + } result.Add(info); } return result; @@ -125,16 +142,6 @@ namespace VocaluxeLib.Xml return type.Name; } - public static T Deserialize(Stream stream) where T : new() - { - return Deserialize(new XmlTextReader(stream) - { - WhitespaceHandling = WhitespaceHandling.Significant, - Normalization = true, - XmlResolver = null - }); - } - private static object _GetValue(XmlNode node, Type type) { if (type.IsEnum) @@ -202,6 +209,11 @@ namespace VocaluxeLib.Xml private static bool _CheckAndSetDefaultValue(ref object result, SFieldInfo field) { + if (field.IsEmbeddedList) + { + _AddList(result, field, new List()); + return true; + } object[] defAtt = field.Info.GetCustomAttributes(typeof(DefaultValueAttribute), false); if (defAtt.Length == 0) return field.IsNullable; @@ -237,11 +249,11 @@ namespace VocaluxeLib.Xml List fields = _GetFields(result.GetType(), attributes); int curField = 0; - List subValues = new List(); - SFieldInfo curListField = new SFieldInfo(); - string curListName = null; if (nodes != null) { + List subValues = new List(); + SFieldInfo curListField = new SFieldInfo(); + string curListName = null; foreach (XmlNode node in nodes) { if (node is XmlComment) @@ -288,6 +300,12 @@ namespace VocaluxeLib.Xml else { object value = _GetValue(node, field.Info.FieldType); + if (field.IsNormalized) + { + if (field.IsNullable && !((float?)value).Value.IsInRange(0, 1) || + !field.IsNullable && !((float)value).IsInRange(0, 1)) + throw new XmlException("Value in " + _FindXPath(node) + " is not normalized. (Value=" + value + ")"); + } field.Info.SetValue(result, value); curField++; } @@ -320,5 +338,25 @@ namespace VocaluxeLib.Xml _ProcessChildNodes(xDoc.DocumentElement, ref result, false); return (T)result; } + + public static T Deserialize(Stream stream) where T : new() + { + return Deserialize(new XmlTextReader(stream) + { + WhitespaceHandling = WhitespaceHandling.Significant, + Normalization = true, + XmlResolver = null + }); + } + + public static T Deserialize(TextReader textReader) where T : new() + { + return Deserialize(new XmlTextReader(textReader) + { + WhitespaceHandling = WhitespaceHandling.Significant, + Normalization = true, + XmlResolver = null + }); + } } } \ No newline at end of file