From 33618b4c970a928aa422d7634ab81dd55a529dbe Mon Sep 17 00:00:00 2001 From: Flamefire Date: Mon, 17 Nov 2014 19:27:43 +0100 Subject: [PATCH] Use extra class for xml exception Add handler class for xml errors Fix testcases --- Vocaluxe/Base/CConfig.cs | 16 +- Vocaluxe/Base/CCover.cs | 5 +- Vocaluxe/Base/CMain.cs | 1 - Vocaluxe/Base/ThemeSystem/CSkin.cs | 5 +- Vocaluxe/Properties/AssemblyInfo.cs | 2 +- VocaluxeLib/IBasic.cs | 1 - VocaluxeLib/Profile/CProfile.cs | 3 +- VocaluxeLib/Xml/CTypeExtensions.cs | 27 ++- VocaluxeLib/Xml/CXmlDeserializer.cs | 201 +++++++++++++++----- VocaluxeLib/Xml/SFieldInfo.cs | 93 +++++++++ VocaluxeTests/TestXmlFiles/Dictionary`2.xml | 34 ++++ VocaluxeTests/XmlSerializerTest.cs | 17 +- 12 files changed, 334 insertions(+), 71 deletions(-) create mode 100644 VocaluxeLib/Xml/SFieldInfo.cs create mode 100644 VocaluxeTests/TestXmlFiles/Dictionary`2.xml diff --git a/Vocaluxe/Base/CConfig.cs b/Vocaluxe/Base/CConfig.cs index 07413fc3..62ed6143 100644 --- a/Vocaluxe/Base/CConfig.cs +++ b/Vocaluxe/Base/CConfig.cs @@ -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(_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) { diff --git a/Vocaluxe/Base/CCover.cs b/Vocaluxe/Base/CCover.cs index e4cebe8e..fb621f16 100644 --- a/Vocaluxe/Base/CCover.cs +++ b/Vocaluxe/Base/CCover.cs @@ -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(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; } diff --git a/Vocaluxe/Base/CMain.cs b/Vocaluxe/Base/CMain.cs index 924cba2b..f5b00c13 100644 --- a/Vocaluxe/Base/CMain.cs +++ b/Vocaluxe/Base/CMain.cs @@ -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; diff --git a/Vocaluxe/Base/ThemeSystem/CSkin.cs b/Vocaluxe/Base/ThemeSystem/CSkin.cs index 80c799d4..65edc203 100644 --- a/Vocaluxe/Base/ThemeSystem/CSkin.cs +++ b/Vocaluxe/Base/ThemeSystem/CSkin.cs @@ -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(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++) diff --git a/Vocaluxe/Properties/AssemblyInfo.cs b/Vocaluxe/Properties/AssemblyInfo.cs index 495dca5c..3e00fede 100644 --- a/Vocaluxe/Properties/AssemblyInfo.cs +++ b/Vocaluxe/Properties/AssemblyInfo.cs @@ -51,4 +51,4 @@ using System.Runtime.InteropServices; [assembly: AssemblyVersion("0.3.0.83")] [assembly: AssemblyFileVersion("0.3.0.83")] -[assembly: AssemblyInformationalVersion("GITVERSION")] \ No newline at end of file +[assembly: AssemblyInformationalVersion("GITVERSION")] diff --git a/VocaluxeLib/IBasic.cs b/VocaluxeLib/IBasic.cs index 1a9a82a7..765086c6 100644 --- a/VocaluxeLib/IBasic.cs +++ b/VocaluxeLib/IBasic.cs @@ -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; diff --git a/VocaluxeLib/Profile/CProfile.cs b/VocaluxeLib/Profile/CProfile.cs index 8b769564..97c0474b 100644 --- a/VocaluxeLib/Profile/CProfile.cs +++ b/VocaluxeLib/Profile/CProfile.cs @@ -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; } diff --git a/VocaluxeLib/Xml/CTypeExtensions.cs b/VocaluxeLib/Xml/CTypeExtensions.cs index 15a3c564..39c47fe5 100644 --- a/VocaluxeLib/Xml/CTypeExtensions.cs +++ b/VocaluxeLib/Xml/CTypeExtensions.cs @@ -44,7 +44,9 @@ namespace VocaluxeLib.Xml /// Attribute for float fields to enforce normalized (0<=x<=1) values /// [AttributeUsage(AttributeTargets.Field)] - public class XmlNormalizedAttribute : Attribute {} + public class XmlNormalizedAttribute : XmlRangedAttribute { + public XmlNormalizedAttribute() : base(0, 1) {} + } /// /// 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()) - { Debug.Assert(info.Type == typeof(float) || (info.IsNullable && info.SubType == typeof(float)), "Only floats can be normalized"); - info.IsNormalized = true; - } info.Ranged = field.GetAttribute(); - 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(); diff --git a/VocaluxeLib/Xml/CXmlDeserializer.cs b/VocaluxeLib/Xml/CXmlDeserializer.cs index a6299991..2bdb2361 100644 --- a/VocaluxeLib/Xml/CXmlDeserializer.cs +++ b/VocaluxeLib/Xml/CXmlDeserializer.cs @@ -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 /// @@ -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 + { + /// + /// Gets called for every error that occurs during xml reading. + /// Recommended way of handling is throwing that error and log it
+ /// 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 + ///
+ /// Error that would be thrown + void HandleError(CXmlException e); + } + + /// + /// Class for simple construction of error handlers by using a delegate + /// + 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; + + /// + /// Creates a new XmlDeserializer + /// + /// Class to be used for error callbacks, if not given a default handler will be used which throws errors and logs warnings + public CXmlDeserializer(IXmlErrorHandler errorHandler = null) + { + _ErrorHandler = errorHandler ?? new CXmlDefaultErrorHandler(); + } + /// /// Returns the value if the given node /// /// Node to process /// Type of the object at that node /// Name of the sub nodes for array types(Array,List,Dictionary), can be set by XmlArrayItemAttribute and defaults to the type name - /// If given, no new class is created and value is used instead + /// If given, no new class is created and value is used instead, also used as default value /// 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(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); diff --git a/VocaluxeLib/Xml/SFieldInfo.cs b/VocaluxeLib/Xml/SFieldInfo.cs new file mode 100644 index 00000000..bf9eaad3 --- /dev/null +++ b/VocaluxeLib/Xml/SFieldInfo.cs @@ -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 . +#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; + /// + /// List with child elements ( + /// + /// + /// + /// ) + /// + public bool IsList; + /// + /// List w/o child elements() + /// + public bool IsEmbeddedList; + /// + /// List where the element names are the keys + /// + public bool IsDictionary; + /// + /// Byte arrays w/o XmlArrayAttribute are serialized as Base64-Encoded strings + /// + public bool IsByteArray; + public bool IsNullable; + public XmlRangedAttribute Ranged; + /// + /// Type of subnodes (array/list elements or dictionary values) + /// + public Type SubType; + /// + /// Name of the subnodes + /// + 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[] {}); + } + } +} \ No newline at end of file diff --git a/VocaluxeTests/TestXmlFiles/Dictionary`2.xml b/VocaluxeTests/TestXmlFiles/Dictionary`2.xml new file mode 100644 index 00000000..299972ec --- /dev/null +++ b/VocaluxeTests/TestXmlFiles/Dictionary`2.xml @@ -0,0 +1,34 @@ + + + Deutsch + Vocaluxe + und + Exit + Speichern + Zurück + Start + Audio-Streams + Video-Streams + Textures + ToneAbs + Max. Volume + Geladene Songs + Maus + Speicherverbrauch + Normal + Duett + Medley + Kurz-Version + Vocal Hero + Superstar + Hit-Künstler + Sternchen + Fortgeschritten + Möchtegern + Amateur + Nichtskönner + Gast + Normaler Benutzer + Administrator + Tastatur + \ No newline at end of file diff --git a/VocaluxeTests/XmlSerializerTest.cs b/VocaluxeTests/XmlSerializerTest.cs index 791ecf0e..c8276e06 100644 --- a/VocaluxeTests/XmlSerializerTest.cs +++ b/VocaluxeTests/XmlSerializerTest.cs @@ -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(sTmp); + _AssertFail(sTmp); } } @@ -196,7 +195,7 @@ namespace VocaluxeTests foreach (string s1 in s) { string sTmp = s1; - _AssertFail(sTmp); + _AssertFail(sTmp); } } @@ -253,7 +252,7 @@ namespace VocaluxeTests _AssertSerDeserMatch(_XMLList[2]); res = ser.Serialize(foo); Assert.AreEqual(_XMLList[2], res, "Serialization2 failed"); - _AssertFail(_Empty); + _AssertFail(_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(_Empty); + _AssertFail(_Empty); } private const string _XMLListEmb = _Head + @" @@ -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(_Empty); + _AssertFail(_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(_Empty); + _AssertFail(_Empty); } [TestMethod] @@ -377,7 +376,7 @@ namespace VocaluxeTests public void TestIgnore() { _AssertSerDeserMatch(_XmlIgnore); - _AssertFail(_XmlIgnore2); + _AssertFail(_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) ? "resources" : foo); + string newXml = ser.Serialize(foo, type == typeof(Dictionary) ? "resources" : null); // Typename will be uppercase but input is lowercase newXml = newXml.Replace("