Use extra class for xml exception
Add handler class for xml errors Fix testcases
This commit is contained in:
1 parent
a2aafd4614
commit
33618b4c97
12 files changed
+334
-71
No files matched your search
@@ -43,9 +43,12 @@ namespace Vocaluxe.Base
|
||||
|
||||
// ReSharper disable UnassignedField.Global
|
||||
#pragma warning disable 649
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
public struct SConfigInfo
|
||||
// ReSharper restore MemberCanBePrivate.Global
|
||||
{
|
||||
// ReSharper disable NotAccessedField.Global
|
||||
// ReSharper disable NotAccessedField.Local
|
||||
public string Version;
|
||||
public string Time;
|
||||
public string Platform;
|
||||
@@ -54,6 +57,7 @@ namespace Vocaluxe.Base
|
||||
public int Screens;
|
||||
public string PrimaryScreenResolution;
|
||||
public string Directory;
|
||||
// ReSharper restore NotAccessedField.Local
|
||||
// ReSharper restore NotAccessedField.Global
|
||||
}
|
||||
|
||||
@@ -248,10 +252,20 @@ namespace Vocaluxe.Base
|
||||
_Initialized = true;
|
||||
}
|
||||
|
||||
private static bool _XmlErrorsOccured;
|
||||
|
||||
private static void _HandleXmlError(CXmlException e)
|
||||
{
|
||||
_XmlErrorsOccured = true;
|
||||
}
|
||||
|
||||
private static void _LoadConfig()
|
||||
{
|
||||
var xml = new CXmlDeserializer();
|
||||
_XmlErrorsOccured = false;
|
||||
var xml = new CXmlDeserializer(new CXmlErrorHandler(_HandleXmlError));
|
||||
Config = xml.Deserialize<SConfig>(_FileConfig);
|
||||
if (_XmlErrorsOccured)
|
||||
CLog.LogError("There were some warnings or errors loading the config file. Some values might have been reset to their defaults.");
|
||||
|
||||
if (Config.Game.SongFolder.Length > 0)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,6 @@ using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Linq;
|
||||
using VocaluxeLib;
|
||||
using VocaluxeLib.Draw;
|
||||
@@ -179,9 +178,9 @@ namespace Vocaluxe.Base
|
||||
{
|
||||
theme = xml.Deserialize<SThemeCover>(Path.Combine(folderPath, file));
|
||||
}
|
||||
catch (XmlException e)
|
||||
catch (CXmlException e)
|
||||
{
|
||||
CLog.LogError("Error loading cover theme " + file + ": " + e.Message);
|
||||
CLog.LogError("Error loading cover theme " + file + ": " + e);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using System.Xml;
|
||||
using Vocaluxe.Base.Fonts;
|
||||
using Vocaluxe.Base.ThemeSystem;
|
||||
using VocaluxeLib;
|
||||
|
||||
@@ -19,7 +19,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using VocaluxeLib;
|
||||
using VocaluxeLib.Draw;
|
||||
@@ -98,9 +97,9 @@ namespace Vocaluxe.Base.ThemeSystem
|
||||
{
|
||||
_Required = xml.Deserialize<SRequiredElements>(path);
|
||||
}
|
||||
catch (XmlException e)
|
||||
catch (CXmlException e)
|
||||
{
|
||||
CLog.LogError("Error reading required elements: " + e.Message);
|
||||
CLog.LogError("Error reading required elements: " + e);
|
||||
return false;
|
||||
}
|
||||
for (int i = 1; i <= CSettings.MaxNumPlayer; i++)
|
||||
|
||||
@@ -51,4 +51,4 @@ using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyVersion("0.3.0.83")]
|
||||
[assembly: AssemblyFileVersion("0.3.0.83")]
|
||||
[assembly: AssemblyInformationalVersion("GITVERSION")]
|
||||
[assembly: AssemblyInformationalVersion("GITVERSION")]
|
||||
@@ -19,7 +19,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using System.Xml;
|
||||
using VocaluxeLib.Draw;
|
||||
using VocaluxeLib.Game;
|
||||
using VocaluxeLib.Menu;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using VocaluxeLib.Xml;
|
||||
|
||||
@@ -116,7 +115,7 @@ namespace VocaluxeLib.Profile
|
||||
}
|
||||
catch (Exception e2)
|
||||
{
|
||||
if (!(e2 is XmlException))
|
||||
if (!(e2 is CXmlException))
|
||||
e = e2;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,9 @@ namespace VocaluxeLib.Xml
|
||||
/// Attribute for float fields to enforce normalized (0<=x<=1) values
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class XmlNormalizedAttribute : Attribute {}
|
||||
public class XmlNormalizedAttribute : XmlRangedAttribute {
|
||||
public XmlNormalizedAttribute() : base(0, 1) {}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute for int fields to enforce values in the given range
|
||||
@@ -60,6 +62,23 @@ namespace VocaluxeLib.Xml
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
public bool IsValid(Type type, object value)
|
||||
{
|
||||
if (type == typeof(int))
|
||||
return ((int)value).IsInRange(Min, Max);
|
||||
if (type == typeof(float))
|
||||
return ((float)value).IsInRange(Min, Max);
|
||||
if (type == typeof(double))
|
||||
return ((double)value).IsInRange(Min, Max);
|
||||
Debug.Assert(false, "Ranged attribute has invalid type");
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Min + "-" + Max;
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper restore InconsistentNaming
|
||||
@@ -153,12 +172,10 @@ namespace VocaluxeLib.Xml
|
||||
}
|
||||
|
||||
if (field.HasAttribute<XmlNormalizedAttribute>())
|
||||
{
|
||||
Debug.Assert(info.Type == typeof(float) || (info.IsNullable && info.SubType == typeof(float)), "Only floats can be normalized");
|
||||
info.IsNormalized = true;
|
||||
}
|
||||
info.Ranged = field.GetAttribute<XmlRangedAttribute>();
|
||||
Debug.Assert(info.Ranged == null || info.Type == typeof(int) || info.Type == typeof(float) || info.Type == typeof(double),
|
||||
Type tmpType = info.IsNullable ? info.SubType : info.Type;
|
||||
Debug.Assert(info.Ranged == null || tmpType == typeof(int) || tmpType == typeof(float) || tmpType == typeof(double),
|
||||
"Only ints,floats and double can be ranged");
|
||||
|
||||
DefaultValueAttribute defAttr = field.GetAttribute<DefaultValueAttribute>();
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -28,7 +27,7 @@ using System.Xml;
|
||||
|
||||
namespace VocaluxeLib.Xml
|
||||
{
|
||||
public class CXmlDeserializer
|
||||
public class CXmlException : Exception
|
||||
{
|
||||
#region Debug Helpers
|
||||
/// <summary>
|
||||
@@ -87,13 +86,105 @@ namespace VocaluxeLib.Xml
|
||||
}
|
||||
#endregion Debug Helpers
|
||||
|
||||
private readonly XmlNode _Node;
|
||||
public readonly bool IsError;
|
||||
|
||||
public CXmlException(string msg, XmlNode node, bool isError = true)
|
||||
: base(msg)
|
||||
{
|
||||
IsError = isError;
|
||||
_Node = node;
|
||||
}
|
||||
|
||||
public override string Message
|
||||
{
|
||||
get { return ToString(); }
|
||||
}
|
||||
|
||||
public override String ToString()
|
||||
{
|
||||
string xPath = _Node == null ? "" : _GetXPath(_Node);
|
||||
string type = IsError ? "Error" : "Warning";
|
||||
return type + ": " + base.Message.Replace("%n", xPath);
|
||||
}
|
||||
}
|
||||
|
||||
public class CXmlInvalidValueException : CXmlException
|
||||
{
|
||||
private readonly string _Value;
|
||||
|
||||
public CXmlInvalidValueException(string msg, XmlNode node, string value, bool isError = true) : base(msg, node, isError)
|
||||
{
|
||||
_Value = value;
|
||||
}
|
||||
|
||||
public override String ToString()
|
||||
{
|
||||
return base.ToString().Replace("%v", _Value);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IXmlErrorHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets called for every error that occurs during xml reading.
|
||||
/// Recommended way of handling is throwing that error and log it<br />
|
||||
/// However if the function returns without throwing a fallback solution is applied to continue reading where possible e.g. by using default values or ignoring the element
|
||||
/// </summary>
|
||||
/// <param name="e">Error that would be thrown</param>
|
||||
void HandleError(CXmlException e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class for simple construction of error handlers by using a delegate
|
||||
/// </summary>
|
||||
public class CXmlErrorHandler : IXmlErrorHandler
|
||||
{
|
||||
public delegate void HandleErrorDelegate(CXmlException e);
|
||||
|
||||
private readonly HandleErrorDelegate _HandleError;
|
||||
|
||||
public CXmlErrorHandler(HandleErrorDelegate handleError)
|
||||
{
|
||||
_HandleError = handleError;
|
||||
}
|
||||
|
||||
public void HandleError(CXmlException e)
|
||||
{
|
||||
_HandleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public class CXmlDeserializer
|
||||
{
|
||||
private class CXmlDefaultErrorHandler : IXmlErrorHandler
|
||||
{
|
||||
public void HandleError(CXmlException e)
|
||||
{
|
||||
if (e.IsError)
|
||||
throw e;
|
||||
CBase.Log.LogError(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private readonly IXmlErrorHandler _ErrorHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new XmlDeserializer
|
||||
/// </summary>
|
||||
/// <param name="errorHandler">Class to be used for error callbacks, if not given a default handler will be used which throws errors and logs warnings</param>
|
||||
public CXmlDeserializer(IXmlErrorHandler errorHandler = null)
|
||||
{
|
||||
_ErrorHandler = errorHandler ?? new CXmlDefaultErrorHandler();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the value if the given node
|
||||
/// </summary>
|
||||
/// <param name="node">Node to process</param>
|
||||
/// <param name="type">Type of the object at that node</param>
|
||||
/// <param name="subName">Name of the sub nodes for array types(Array,List,Dictionary), can be set by XmlArrayItemAttribute and defaults to the type name</param>
|
||||
/// <param name="value">If given, no new class is created and value is used instead</param>
|
||||
/// <param name="value">If given, no new class is created and value is used instead, also used as default value</param>
|
||||
/// <returns></returns>
|
||||
private object _GetValue(XmlNode node, Type type, string subName = null, object value = null)
|
||||
{
|
||||
@@ -106,13 +197,14 @@ namespace VocaluxeLib.Xml
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new XmlException("Invalid value in " + _GetXPath(node));
|
||||
_ErrorHandler.HandleError(new CXmlInvalidValueException("Invalid value '%v' in %n", node, stringValue));
|
||||
return value;
|
||||
}
|
||||
}
|
||||
if (type == typeof(string))
|
||||
return node.InnerText;
|
||||
if (type.IsPrimitive)
|
||||
return _GetPrimitiveValue(node, type);
|
||||
return _GetPrimitiveValue(node, type) ?? value;
|
||||
if (type.IsNullable())
|
||||
{
|
||||
if (!node.HasChildNodes)
|
||||
@@ -132,9 +224,10 @@ namespace VocaluxeLib.Xml
|
||||
if (subNode is XmlComment)
|
||||
continue;
|
||||
if (subName == subNode.Name.ToLowerInvariant() && !subNode.Name.ToLowerInvariant().StartsWith(subName))
|
||||
throw new XmlException("Invalid list entry '" + subNode.Name + "' in " + _GetXPath(node) + "; Expected: " + subName);
|
||||
_ErrorHandler.HandleError(new CXmlException("Invalid list entry '" + subNode.Name + "' in %n; Expected: " + subName, node));
|
||||
object subValue = _GetValue(subNode, subType);
|
||||
subValues.Add(subValue);
|
||||
if (subValue != null)
|
||||
subValues.Add(subValue);
|
||||
}
|
||||
if (value == null)
|
||||
return _CreateList(type, subValues);
|
||||
@@ -152,22 +245,24 @@ namespace VocaluxeLib.Xml
|
||||
{
|
||||
if (subNode is XmlComment)
|
||||
continue;
|
||||
object subValue = _GetValue(subNode, subType);
|
||||
string key;
|
||||
if (subName != null)
|
||||
{
|
||||
if (subName != subNode.Name.ToLowerInvariant() && !subNode.Name.ToLowerInvariant().StartsWith(subName))
|
||||
throw new XmlException("Invalid dictionary entry '" + subNode.Name + "' in " + _GetXPath(node) + "; Expected: " + subName);
|
||||
if (subNode.Attributes == null)
|
||||
throw new XmlException("'name' attribute is missing in " + _GetXPath(subNode));
|
||||
XmlNode nameAtt = subNode.Attributes.GetNamedItem("name");
|
||||
_ErrorHandler.HandleError(new CXmlException("Invalid dictionary entry '" + subNode.Name + "' in %n; Expected: " + subName, node));
|
||||
XmlNode nameAtt = (subNode.Attributes == null) ? null : subNode.Attributes.GetNamedItem("name");
|
||||
if (nameAtt == null)
|
||||
throw new XmlException("'name' attribute is missing in " + _GetXPath(subNode));
|
||||
{
|
||||
_ErrorHandler.HandleError(new CXmlException("'name' attribute is missing in %n", subNode));
|
||||
continue;
|
||||
}
|
||||
key = nameAtt.Value;
|
||||
}
|
||||
else
|
||||
key = subNode.Name;
|
||||
add.Invoke(dict, new object[] {key, subValue});
|
||||
object subValue = _GetValue(subNode, subType);
|
||||
if (subValue != null)
|
||||
add.Invoke(dict, new object[] {key, subValue});
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
@@ -180,7 +275,8 @@ namespace VocaluxeLib.Xml
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new XmlException("Could not create instance of " + _GetXPath(node) + "(Type=" + type.Name + ")");
|
||||
_ErrorHandler.HandleError(new CXmlException("Could not create instance of %n(Type=" + type.Name + ")", node));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
_ReadChildNodes(node, value, true);
|
||||
@@ -203,7 +299,7 @@ namespace VocaluxeLib.Xml
|
||||
int p = nodeVal.IndexOf(',');
|
||||
if (p > 0 && p >= nodeVal.Length - 3)
|
||||
{
|
||||
CBase.Log.LogError("German number format converted to english in " + _GetXPath(node));
|
||||
_ErrorHandler.HandleError(new CXmlInvalidValueException("German number format converted to English in %n", node, nodeVal, false));
|
||||
char[] tmp = nodeVal.ToCharArray();
|
||||
tmp[p] = '.';
|
||||
nodeVal = new string(tmp);
|
||||
@@ -212,11 +308,13 @@ namespace VocaluxeLib.Xml
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
throw new XmlException("Invalid format in " + _GetXPath(node) + ": '" + nodeVal + "' (" + e.Message + ")");
|
||||
_ErrorHandler.HandleError(new CXmlInvalidValueException("Invalid format in %n: '%v' (" + e.Message + ")", node, nodeVal));
|
||||
return null;
|
||||
}
|
||||
catch (InvalidCastException e)
|
||||
{
|
||||
throw new XmlException(e.Message + " in " + _GetXPath(node) + ": '" + nodeVal + "'");
|
||||
_ErrorHandler.HandleError(new CXmlInvalidValueException(e.Message + " in %n: '%v'", node, nodeVal));
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -324,16 +422,29 @@ namespace VocaluxeLib.Xml
|
||||
}
|
||||
if (curField >= fields.Count)
|
||||
{
|
||||
string msg = "Unexpected element: " + _GetXPath(node);
|
||||
string msg = "Unexpected element: %n";
|
||||
if (fields.Count > 0)
|
||||
msg += " Expected: " + string.Join(", ", fields.Select(f => f.Name));
|
||||
throw new XmlException(msg);
|
||||
_ErrorHandler.HandleError(new CXmlException(msg, node));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field.IsByteArray)
|
||||
{
|
||||
field.SetValue(o, Convert.FromBase64String(node.InnerText));
|
||||
fields.RemoveAt(curField);
|
||||
fields.RemoveAt(curField); //Do this also on error
|
||||
byte[] value;
|
||||
try
|
||||
{
|
||||
value = Convert.FromBase64String(node.InnerText);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_ErrorHandler.HandleError(new CXmlInvalidValueException("Invalid value in %n: %v", node, node.InnerText));
|
||||
if (!_CheckAndSetDefaultValue(o, field))
|
||||
_ErrorHandler.HandleError(new CXmlException("No default value for %n", node));
|
||||
continue;
|
||||
}
|
||||
field.SetValue(o, value);
|
||||
}
|
||||
else if (field.IsEmbeddedList)
|
||||
{
|
||||
@@ -344,36 +455,30 @@ namespace VocaluxeLib.Xml
|
||||
embLists.Add(field.Name, entry);
|
||||
}
|
||||
object subValue = _GetValue(node, field.SubType);
|
||||
entry.Item2.Add(subValue);
|
||||
if (subValue != null)
|
||||
entry.Item2.Add(subValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
fields.RemoveAt(curField); //Do this also on error
|
||||
object value = _GetValue(node, field.Type, field.ArrayItemName);
|
||||
if (field.IsNormalized)
|
||||
if (value == null)
|
||||
{
|
||||
if (field.IsNullable && !((float?)value).Value.IsInRange(0, 1) ||
|
||||
!field.IsNullable && !((float)value).IsInRange(0, 1))
|
||||
throw new XmlException("Value in " + _GetXPath(node) + " is not normalized. (Value=" + value + ")");
|
||||
}
|
||||
if (field.Ranged != null && value != null)
|
||||
{
|
||||
bool ok = false;
|
||||
if (field.Type == typeof(int))
|
||||
ok = ((int)value).IsInRange(field.Ranged.Min, field.Ranged.Max);
|
||||
else if (field.Type == typeof(float))
|
||||
ok = ((float)value).IsInRange(field.Ranged.Min, field.Ranged.Max);
|
||||
else if (field.Type == typeof(double))
|
||||
ok = ((double)value).IsInRange(field.Ranged.Min, field.Ranged.Max);
|
||||
else
|
||||
Debug.Assert(false, "Ranged attribute has invalid type");
|
||||
if (!ok)
|
||||
if (_CheckAndSetDefaultValue(o, field))
|
||||
continue;
|
||||
if (!field.IsNullable)
|
||||
{
|
||||
throw new XmlException("Value in " + _GetXPath(node) + " is not in the range " + field.Ranged.Min + "-" + field.Ranged.Max + ". (Value=" + value +
|
||||
")");
|
||||
_ErrorHandler.HandleError(new CXmlException("No default value for unset field at %n", node));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (field.Ranged != null && value != null && !field.Ranged.IsValid(field.IsNullable ? field.SubType : field.Type, value))
|
||||
{
|
||||
_ErrorHandler.HandleError(new CXmlInvalidValueException("Value in %n is not in the range " + field.Ranged +
|
||||
". (Value=%v)", node, value.ToString()));
|
||||
}
|
||||
|
||||
field.SetValue(o, value);
|
||||
fields.RemoveAt(curField);
|
||||
}
|
||||
}
|
||||
//Add embedded lists
|
||||
@@ -386,7 +491,7 @@ namespace VocaluxeLib.Xml
|
||||
foreach (SFieldInfo field in fields)
|
||||
{
|
||||
if (!_CheckAndSetDefaultValue(o, field))
|
||||
throw new XmlException("element: " + field.Name + " is missing in " + _GetXPath(parent));
|
||||
_ErrorHandler.HandleError(new CXmlException("element: " + field.Name + " is missing in %n", parent));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,12 +505,18 @@ namespace VocaluxeLib.Xml
|
||||
private T _Deserialize<T>(XmlReader reader, object o) where T : new()
|
||||
{
|
||||
if (reader.IsEmptyElement)
|
||||
{
|
||||
_ErrorHandler.HandleError(new CXmlException("No content in xml!", null));
|
||||
return (T)o;
|
||||
}
|
||||
|
||||
XmlDocument xDoc = new XmlDocument();
|
||||
xDoc.Load(reader);
|
||||
if (xDoc.DocumentElement == null)
|
||||
throw new XmlException("No root element found!");
|
||||
{
|
||||
_ErrorHandler.HandleError(new CXmlException("Root element not found!", null));
|
||||
return (T)o;
|
||||
}
|
||||
try
|
||||
{
|
||||
o = _GetValue(xDoc.DocumentElement, o.GetType(), o.GetType().GetSubTypeName(), o);
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
#region license
|
||||
// This file is part of Vocaluxe.
|
||||
//
|
||||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vocaluxe is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace VocaluxeLib.Xml
|
||||
{
|
||||
public struct SFieldInfo
|
||||
{
|
||||
private readonly FieldInfo _Field;
|
||||
private readonly PropertyInfo _Property;
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get { return _Field != null ? _Field.FieldType : _Property.PropertyType; }
|
||||
}
|
||||
public string Name;
|
||||
public string AltName;
|
||||
public object DefaultValue;
|
||||
public bool HasDefaultValue;
|
||||
public bool IsAttribute;
|
||||
/// <summary>
|
||||
/// List with child elements (
|
||||
/// <List>
|
||||
/// <El /><El />
|
||||
/// </List>
|
||||
/// )
|
||||
/// </summary>
|
||||
public bool IsList;
|
||||
/// <summary>
|
||||
/// List w/o child elements(<List /><List />)
|
||||
/// </summary>
|
||||
public bool IsEmbeddedList;
|
||||
/// <summary>
|
||||
/// List where the element names are the keys
|
||||
/// </summary>
|
||||
public bool IsDictionary;
|
||||
/// <summary>
|
||||
/// Byte arrays w/o XmlArrayAttribute are serialized as Base64-Encoded strings
|
||||
/// </summary>
|
||||
public bool IsByteArray;
|
||||
public bool IsNullable;
|
||||
public XmlRangedAttribute Ranged;
|
||||
/// <summary>
|
||||
/// Type of subnodes (array/list elements or dictionary values)
|
||||
/// </summary>
|
||||
public Type SubType;
|
||||
/// <summary>
|
||||
/// Name of the subnodes
|
||||
/// </summary>
|
||||
public string ArrayItemName;
|
||||
|
||||
public SFieldInfo(FieldInfo field)
|
||||
: this()
|
||||
{
|
||||
_Field = field;
|
||||
}
|
||||
|
||||
public SFieldInfo(PropertyInfo property)
|
||||
: this()
|
||||
{
|
||||
_Property = property;
|
||||
}
|
||||
|
||||
public void SetValue(object o, object value)
|
||||
{
|
||||
if (_Field != null)
|
||||
_Field.SetValue(o, value);
|
||||
else
|
||||
_Property.SetValue(o, value, new object[] {});
|
||||
}
|
||||
|
||||
public object GetValue(object o)
|
||||
{
|
||||
return (_Field != null) ? _Field.GetValue(o) : _Property.GetValue(o, new object[] {});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="language">Deutsch</string>
|
||||
<string name="TR_PROGRAM_NAME">Vocaluxe</string>
|
||||
<string name="TR_GENERAL_AND">und</string>
|
||||
<string name="TR_BUTTON_EXIT">Exit</string>
|
||||
<string name="TR_BUTTON_SAVE">Speichern</string>
|
||||
<string name="TR_BUTTON_BACK">Zurück</string>
|
||||
<string name="TR_BUTTON_START">Start</string>
|
||||
<string name="TR_DEBUG_AUDIO_STREAMS">Audio-Streams</string>
|
||||
<string name="TR_DEBUG_VIDEO_STREAMS">Video-Streams</string>
|
||||
<string name="TR_DEBUG_TEXTURES">Textures</string>
|
||||
<string name="TR_DEBUG_TONE_ABS">ToneAbs</string>
|
||||
<string name="TR_DEBUG_MAX_VOLUME">Max. Volume</string>
|
||||
<string name="TR_DEBUG_SONGS">Geladene Songs</string>
|
||||
<string name="TR_DEBUG_MOUSE">Maus</string>
|
||||
<string name="TR_DEBUG_MEMORY">Speicherverbrauch</string>
|
||||
<string name="TR_GAMEMODE_NORMAL">Normal</string>
|
||||
<string name="TR_GAMEMODE_DUET">Duett</string>
|
||||
<string name="TR_GAMEMODE_MEDLEY">Medley</string>
|
||||
<string name="TR_GAMEMODE_SHORTSONG">Kurz-Version</string>
|
||||
<string name="TR_RATING_VOCAL_HERO">Vocal Hero</string>
|
||||
<string name="TR_RATING_SUPERSTAR">Superstar</string>
|
||||
<string name="TR_RATING_LEAD_SINGER">Hit-Künstler</string>
|
||||
<string name="TR_RATING_RISING_STAR">Sternchen</string>
|
||||
<string name="TR_RATING_HOPEFUL">Fortgeschritten</string>
|
||||
<string name="TR_RATING_WANNABE">Möchtegern</string>
|
||||
<string name="TR_RATING_AMATEUR">Amateur</string>
|
||||
<string name="TR_RATING_TONE_DEAF">Nichtskönner</string>
|
||||
<string name="TR_USERROLE_GUEST">Gast</string>
|
||||
<string name="TR_USERROLE_NORMAL">Normaler Benutzer</string>
|
||||
<string name="TR_USERROLE_ADMIN">Administrator</string>
|
||||
<string name="TR_USERROLE_KEYBOARDUSER">Tastatur</string>
|
||||
</resources>
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Vocaluxe.Base;
|
||||
@@ -167,7 +166,7 @@ namespace VocaluxeTests
|
||||
foreach (string s1 in s)
|
||||
{
|
||||
string sTmp = s1;
|
||||
_AssertFail<SBasic, XmlException>(sTmp);
|
||||
_AssertFail<SBasic, CXmlException>(sTmp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +195,7 @@ namespace VocaluxeTests
|
||||
foreach (string s1 in s)
|
||||
{
|
||||
string sTmp = s1;
|
||||
_AssertFail<SBasic, XmlException>(sTmp);
|
||||
_AssertFail<SBasic, CXmlException>(sTmp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +252,7 @@ namespace VocaluxeTests
|
||||
_AssertSerDeserMatch<SList>(_XMLList[2]);
|
||||
res = ser.Serialize(foo);
|
||||
Assert.AreEqual(_XMLList[2], res, "Serialization2 failed");
|
||||
_AssertFail<SList, XmlException>(_Empty);
|
||||
_AssertFail<SList, CXmlException>(_Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -275,7 +274,7 @@ namespace VocaluxeTests
|
||||
Assert.AreEqual(foo.Ints.Length, 0, "Deserialization2 failed");
|
||||
res = ser.Serialize(foo);
|
||||
Assert.AreEqual(_XMLList[2], res, "Serialization2 failed");
|
||||
_AssertFail<SArray, XmlException>(_Empty);
|
||||
_AssertFail<SArray, CXmlException>(_Empty);
|
||||
}
|
||||
|
||||
private const string _XMLListEmb = _Head + @"<root>
|
||||
@@ -319,7 +318,7 @@ namespace VocaluxeTests
|
||||
Assert.AreEqual(foo.Ints.Count, 0, "Deserialization failed");
|
||||
res = ser.Serialize(foo);
|
||||
Assert.AreEqual(_XMLListEmb3, res, "Serialization failed");
|
||||
_AssertFail<SListEmb, XmlException>(_Empty);
|
||||
_AssertFail<SListEmb, CXmlException>(_Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -341,7 +340,7 @@ namespace VocaluxeTests
|
||||
Assert.AreEqual(foo.Ints.Length, 0, "Deserialization failed");
|
||||
res = ser.Serialize(foo);
|
||||
Assert.AreEqual(_XMLListEmb3, res, "Serialization failed");
|
||||
_AssertFail<SArrayEmb, XmlException>(_Empty);
|
||||
_AssertFail<SArrayEmb, CXmlException>(_Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -377,7 +376,7 @@ namespace VocaluxeTests
|
||||
public void TestIgnore()
|
||||
{
|
||||
_AssertSerDeserMatch<SIgnore>(_XmlIgnore);
|
||||
_AssertFail<SIgnore, XmlException>(_XmlIgnore2);
|
||||
_AssertFail<SIgnore, CXmlException>(_XmlIgnore2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -438,7 +437,7 @@ namespace VocaluxeTests
|
||||
}
|
||||
Assert.IsInstanceOfType(foo, type, "Wrong type with " + type.Name);
|
||||
var ser = new CXmlSerializer(type == typeof(CConfig.SConfig));
|
||||
string newXml = ser.Serialize(type == typeof(Dictionary<string, string>) ? "resources" : foo);
|
||||
string newXml = ser.Serialize(foo, type == typeof(Dictionary<string, string>) ? "resources" : null);
|
||||
// Typename will be uppercase but input is lowercase
|
||||
newXml = newXml.Replace("<String", "<string").Replace("</String", "</string");
|
||||
string oldXml = File.ReadAllText(xmlPath);
|
||||
|
||||
Reference in new issue
Block a user