Refactoring and fixes for some special cases (mostly lists)

This commit is contained in:
Flamefire committed 2014-10-24 22:48:47 +02:00
1 parent 8dda647619
commit ad3f01aded
3 files changed
+102 -66

No files matched your search

+7 -2
View File
@@ -23,6 +23,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using VocaluxeLib; using VocaluxeLib;
using VocaluxeLib.Draw; using VocaluxeLib.Draw;
using VocaluxeLib.Menu;
using VocaluxeLib.Songs; using VocaluxeLib.Songs;
using VocaluxeLib.Xml; using VocaluxeLib.Xml;
@@ -168,10 +169,14 @@ namespace Vocaluxe.Base
private static void _TestNewLoad(string path) private static void _TestNewLoad(string path)
{ {
SThemeCover theme; /*SThemeCover theme;
using (var stream = new FileStream(path, FileMode.Open)) using (var stream = new FileStream(path, FileMode.Open))
theme = CMyXmlDeserializer.Deserialize<SThemeCover>(stream); theme = CMyXmlDeserializer.Deserialize<SThemeCover>(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<STheme>(stream);
string foo = themescreen.Informations.ScreenName;
} }
/// <summary> /// <summary>
+2 -2
View File
@@ -119,7 +119,7 @@ namespace VocaluxeLib
[XmlRoot("Color")] [XmlRoot("Color")]
public struct SThemeColor public struct SThemeColor
{ {
[DefaultValue(null), XmlAttribute] public string Name; [DefaultValue(null), XmlAttribute] public string Name;
public float? R; public float? R;
public float? G; public float? G;
public float? B; public float? B;
@@ -237,7 +237,7 @@ namespace VocaluxeLib
[XmlRoot("Reflection")] [XmlRoot("Reflection")]
public struct SReflection public struct SReflection
{ {
[XmlAttribute(AttributeName = "Enabled")] public bool Enabled; [XmlAttribute] public bool Enabled;
public float Height; public float Height;
public float Space; public float Space;
+93 -62
View File
@@ -18,7 +18,8 @@ namespace VocaluxeLib.Xml
{ {
public string Name; public string Name;
public FieldInfo Info; public FieldInfo Info;
public bool IsList; public bool IsList; //List with child elements (<List><El/><El/></List>)
public bool IsEmbeddedList; //List w/o child elements(<List/><List/>)
public bool IsNullable; public bool IsNullable;
public Type SubType; public Type SubType;
} }
@@ -95,7 +96,13 @@ namespace VocaluxeLib.Xml
if (field.FieldType.IsGenericType) if (field.FieldType.IsGenericType)
{ {
if (field.FieldType.GetGenericTypeDefinition() == typeof(List<>)) 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<>)) else if (field.FieldType.GetGenericTypeDefinition() == typeof(Nullable<>))
info.IsNullable = true; info.IsNullable = true;
info.SubType = field.FieldType.GetGenericArguments()[0]; info.SubType = field.FieldType.GetGenericArguments()[0];
@@ -105,6 +112,18 @@ namespace VocaluxeLib.Xml
return result; 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<T>(Stream stream) where T : new() public static T Deserialize<T>(Stream stream) where T : new()
{ {
return Deserialize<T>(new XmlTextReader(stream) return Deserialize<T>(new XmlTextReader(stream)
@@ -117,60 +136,61 @@ namespace VocaluxeLib.Xml
private static object _GetValue(XmlNode node, Type type) private static object _GetValue(XmlNode node, Type type)
{ {
object value;
if (type.IsEnum) if (type.IsEnum)
{ {
string stringValue = node.InnerText; string stringValue = node.InnerText;
try try
{ {
value = Enum.Parse(type, stringValue); return Enum.Parse(type, stringValue);
} }
catch (Exception) catch (Exception)
{ {
throw new XmlException("Invalid value in " + _FindXPath(node)); 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]; Type subType = type.GetGenericArguments()[0];
value = Activator.CreateInstance(type); String subName = _GetTypeName(subType);
MethodInfo addMethod = value.GetType().GetMethod("Add"); List<object> subValues = new List<object>();
List<object> subValues = new List<object>(node.ChildNodes.Count);
foreach (XmlNode subNode in node.ChildNodes) foreach (XmlNode subNode in node.ChildNodes)
{ {
if (subNode is XmlComment) if (subNode is XmlComment)
continue; continue;
if (subName != subNode.Name)
throw new XmlException("Invalid list entry '" + subNode.Name + "' in " + _FindXPath(node) + "; Expected: " + subName);
object subValue = _GetValue(subNode, subType); object subValue = _GetValue(subNode, subType);
_ProcessChildNodes(subNode, ref subValue, true); _ProcessChildNodes(subNode, ref subValue, true);
subValues.Add(subValue); 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]; Type subType = type.GetGenericArguments()[0];
string stringValue = node.InnerText; return _GetPrimitiveValue(node, subType);
value = Convert.ChangeType(stringValue, subType);
} }
else if (type == typeof(string))
value = node.InnerText; object value = Activator.CreateInstance(type);
else if (!type.IsPrimitive) _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); value = Convert.ChangeType(node.InnerText, type, CultureInfo.InvariantCulture);
_ProcessChildNodes(node, ref value, true);
_ProcessChildNodes(node, ref value, false);
} }
else catch (FormatException)
{ {
string stringValue = node.InnerText; throw new XmlException("Invalid format in " + _FindXPath(node) + ": '" + node.InnerText + "'");
try
{
value = Convert.ChangeType(stringValue, type, CultureInfo.InvariantCulture);
}
catch (FormatException)
{
throw new XmlException("Invalid format in " + _FindXPath(node));
}
} }
return value; return value;
} }
@@ -184,6 +204,23 @@ namespace VocaluxeLib.Xml
return true; return true;
} }
private static object _CreateList(Type type, List<object> 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<object> list)
{
listField.Info.SetValue(result, _CreateList(listField.Info.FieldType, list));
}
private static void _ProcessChildNodes(XmlNode parent, ref object result, bool attributes) private static void _ProcessChildNodes(XmlNode parent, ref object result, bool attributes)
{ {
IEnumerable nodes; IEnumerable nodes;
@@ -210,56 +247,50 @@ namespace VocaluxeLib.Xml
if (node.Name != curListName) if (node.Name != curListName)
{ {
// End an embedded List // End an embedded List
object list = Activator.CreateInstance(curListField.Info.FieldType); _AddList(result, curListField, subValues);
MethodInfo addMethod = curListField.Info.FieldType.GetMethod("Add");
addMethod.Invoke(list, subValues.ToArray());
curListField.Info.SetValue(result, list);
curField++; curField++;
curListName = null; curListName = null;
} }
else
{
// Continue an embedded List
object subValue = _GetValue(node, curListField.SubType);
subValues.Add(subValue);
continue;
}
} }
SFieldInfo field = new SFieldInfo(); 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)
field = fields[curField]; break;
if (field.Name == node.Name) if (!_CheckAndSetDefaultValue(ref result, field))
break; throw new XmlException("Unexpected element: " + _FindXPath(node) + "; Expected: " + field.Name);
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();
}
} }
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); object value = _GetValue(node, field.Info.FieldType);
field.Info.SetValue(result, value); field.Info.SetValue(result, value);
curField++; curField++;
} }
else
{
// Continue an embedded List
object value = _GetValue(node, field.SubType);
subValues.Add(value);
}
} }
if (curListName != null) if (curListName != null)
{ {
// End an embedded List // End an embedded List
object list = Activator.CreateInstance(curListField.Info.FieldType); _AddList(result, curListField, subValues);
MethodInfo addMethod = curListField.Info.FieldType.GetMethod("Add");
addMethod.Invoke(list, subValues.ToArray());
curListField.Info.SetValue(result, list);
curField++; curField++;
} }
} }