Include Dictionaries in serializer
This commit is contained in:
1 parent
ebe531e5eb
commit
6f873c9785
2 files changed
+54
-16
No files matched your search
@@ -48,6 +48,7 @@ namespace VocaluxeLib.Xml
|
||||
public bool IsAttribute;
|
||||
public bool IsList; //List with child elements (<List><El/><El/></List>)
|
||||
public bool IsEmbeddedList; //List w/o child elements(<List/><List/>)
|
||||
public bool IsDictionary; //List where the element names are the keys
|
||||
public bool IsNullable;
|
||||
public bool IsNormalized;
|
||||
public XmlRangedAttribute Ranged;
|
||||
@@ -88,7 +89,7 @@ namespace VocaluxeLib.Xml
|
||||
XmlArrayAttribute array = field.GetAttribute<XmlArrayAttribute>();
|
||||
if (array != null)
|
||||
{
|
||||
Debug.Assert(field.IsList() || field.FieldType.IsArray, "Only lists and arrays can have the array attribute");
|
||||
Debug.Assert(field.FieldType.IsList() || field.FieldType.IsArray, "Only lists and arrays can have the array attribute");
|
||||
Debug.Assert(!info.IsAttribute, "Lists cannot be attributes");
|
||||
info.Name = array.ElementName;
|
||||
info.IsList = true;
|
||||
@@ -102,10 +103,10 @@ namespace VocaluxeLib.Xml
|
||||
info.AltName = altName.AltName;
|
||||
|
||||
if (field.FieldType.IsGenericType)
|
||||
info.SubType = field.FieldType.GetGenericArguments()[0];
|
||||
info.SubType = field.FieldType.GetGenericArguments().Last();
|
||||
if (field.FieldType.IsArray)
|
||||
info.SubType = field.FieldType.GetElementType();
|
||||
if (field.IsList() || field.FieldType.IsArray)
|
||||
if (field.FieldType.IsList() || field.FieldType.IsArray)
|
||||
{
|
||||
if (!info.IsList)
|
||||
{
|
||||
@@ -121,6 +122,11 @@ namespace VocaluxeLib.Xml
|
||||
}
|
||||
else if (field.FieldType.IsNullable())
|
||||
info.IsNullable = true;
|
||||
else if (field.FieldType.IsDictionary())
|
||||
{
|
||||
Debug.Assert(field.FieldType.GetGenericArguments()[0] == typeof(string), "Keys of dictionaries must be strings");
|
||||
info.IsDictionary = true;
|
||||
}
|
||||
|
||||
if (field.HasAttribute<XmlNormalizedAttribute>())
|
||||
{
|
||||
@@ -128,12 +134,13 @@ namespace VocaluxeLib.Xml
|
||||
info.IsNormalized = true;
|
||||
}
|
||||
info.Ranged = field.GetAttribute<XmlRangedAttribute>();
|
||||
Debug.Assert(info.Ranged == null || field.FieldType == typeof(int), "Only ints can be ranged");
|
||||
Debug.Assert(info.Ranged == null || field.FieldType == typeof(int) || field.FieldType == typeof(float) || field.FieldType == typeof(double),
|
||||
"Only ints,floats and double can be ranged");
|
||||
|
||||
DefaultValueAttribute defAttr = field.GetAttribute<DefaultValueAttribute>();
|
||||
if (defAttr != null)
|
||||
{
|
||||
Debug.Assert(!field.IsList(), "Lists cannot have a default value");
|
||||
Debug.Assert(!field.FieldType.IsList(), "Lists cannot have a default value");
|
||||
info.HasDefaultValue = true;
|
||||
info.DefaultValue = defAttr.Value;
|
||||
}
|
||||
@@ -187,14 +194,14 @@ namespace VocaluxeLib.Xml
|
||||
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
|
||||
}
|
||||
|
||||
public static bool IsDictionary(this Type type)
|
||||
{
|
||||
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>);
|
||||
}
|
||||
|
||||
public static bool IsList(this Type type)
|
||||
{
|
||||
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>);
|
||||
}
|
||||
|
||||
public static bool IsList(this FieldInfo field)
|
||||
{
|
||||
return field.FieldType.IsList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,11 +117,24 @@ namespace VocaluxeLib.Xml
|
||||
if (subName != subNode.Name && !subNode.Name.StartsWith(subName))
|
||||
throw new XmlException("Invalid list entry '" + subNode.Name + "' in " + _GetXPath(node) + "; Expected: " + subName);
|
||||
object subValue = _GetValue(subNode, subType);
|
||||
_ReadChildNodes(subNode, ref subValue, true);
|
||||
subValues.Add(subValue);
|
||||
}
|
||||
return _CreateList(type, subValues);
|
||||
}
|
||||
if (type.IsDictionary())
|
||||
{
|
||||
Type subType = type.GetGenericArguments()[1];
|
||||
object dict = Activator.CreateInstance(type);
|
||||
MethodInfo add = type.GetMethod("Add");
|
||||
foreach (XmlNode subNode in node.ChildNodes)
|
||||
{
|
||||
if (subNode is XmlComment)
|
||||
continue;
|
||||
object subValue = _GetValue(subNode, subType);
|
||||
add.Invoke(dict, new object[] {subNode.Name, subValue});
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
object value;
|
||||
try
|
||||
@@ -270,10 +283,18 @@ namespace VocaluxeLib.Xml
|
||||
!field.IsNullable && !((float)value).IsInRange(0, 1))
|
||||
throw new XmlException("Value in " + _GetXPath(node) + " is not normalized. (Value=" + value + ")");
|
||||
}
|
||||
if (field.Ranged != null)
|
||||
if (field.Ranged != null && value != null)
|
||||
{
|
||||
if (field.IsNullable && !((int?)value).Value.IsInRange(field.Ranged.Min, field.Ranged.Max) ||
|
||||
!field.IsNullable && !((int)value).IsInRange(field.Ranged.Min, field.Ranged.Max))
|
||||
bool ok = false;
|
||||
if (field.Info.FieldType == typeof(int))
|
||||
ok = ((int)value).IsInRange(field.Ranged.Min, field.Ranged.Max);
|
||||
else if (field.Info.FieldType == typeof(float))
|
||||
ok = ((float)value).IsInRange(field.Ranged.Min, field.Ranged.Max);
|
||||
else if (field.Info.FieldType == typeof(double))
|
||||
ok = ((double)value).IsInRange(field.Ranged.Min, field.Ranged.Max);
|
||||
else
|
||||
Debug.Assert(false, "Ranged attribute has invalid type");
|
||||
if (!ok)
|
||||
{
|
||||
throw new XmlException("Value in " + _GetXPath(node) + " is not in the range " + field.Ranged.Min + "-" + field.Ranged.Max + ". (Value=" + value +
|
||||
")");
|
||||
@@ -324,6 +345,8 @@ namespace VocaluxeLib.Xml
|
||||
else
|
||||
writer.WriteElementString(name, strVal);
|
||||
}
|
||||
else if (type.IsNullable())
|
||||
_WriteNode(writer, name, type.GetGenericArguments()[0], value, isAttribute, arrayItemName);
|
||||
else if (type.IsList() || type.IsArray)
|
||||
{
|
||||
Debug.Assert(!isAttribute, "Lists cannot be attributes");
|
||||
@@ -335,8 +358,16 @@ namespace VocaluxeLib.Xml
|
||||
_WriteNode(writer, subName, subType, subValue, false);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
else if (type.IsNullable())
|
||||
_WriteNode(writer, name, type.GetGenericArguments()[0], value, isAttribute, arrayItemName);
|
||||
else if (type.IsDictionary())
|
||||
{
|
||||
Debug.Assert(!isAttribute, "Dictionaries cannot be attributes");
|
||||
writer.WriteStartElement(name);
|
||||
Type subType = type.GetGenericArguments()[1];
|
||||
IDictionary dict = (IDictionary)value;
|
||||
foreach (DictionaryEntry entry in dict)
|
||||
_WriteNode(writer, (string)entry.Key, subType, entry.Value, false);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(!isAttribute, "Complex types cannot be attributes");
|
||||
|
||||
Reference in new issue
Block a user