diff --git a/GDSerializer.csproj b/GDSerializer.csproj
index 2128b12..4a5cdce 100644
--- a/GDSerializer.csproj
+++ b/GDSerializer.csproj
@@ -8,7 +8,7 @@
true
true
- 2.0.2
+ 2.0.3
GDSerializer
Carnagion
An XML (de)serialization framework for Godot's C# API.
diff --git a/README.md b/README.md
index 9976fa7..0f96677 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ It supports (de)serialization of almost any C# type including collections and ma
**GDSerializer** is available as a [NuGet package](https://www.nuget.org/packages/GDSerializer/), which can be installed either through an IDE or by manually including the following lines in a Godot project's `.csproj` file:
```xml
-
+
```
Its dependencies may need to be installed as well, in a similar fashion.
diff --git a/Serialization/Serializer.cs b/Serialization/Serializer.cs
index 77d4666..da3b280 100644
--- a/Serialization/Serializer.cs
+++ b/Serialization/Serializer.cs
@@ -103,7 +103,6 @@ public static bool CanSerialize(PropertyInfo property)
&& property.CanWrite
&& !property.GetIndexParameters().Any()
&& property.GetCustomAttribute() is null
- && property.GetMethod.GetCustomAttribute() is null
&& !Serializer.forbiddenTypes.Contains(property.PropertyType)
&& (property.GetCustomAttribute()?.Serializable ?? true);
}
@@ -132,10 +131,9 @@ public XmlNode Serialize(object instance, Type? type = null)
{
type ??= instance.GetType();
- XmlNode element;
-
try
{
+ XmlNode element;
// Use a more specialized serializer if possible
if (this.TryGetSpecialSerializerForType(type, out ISerializer? serializer))
{
@@ -144,23 +142,10 @@ public XmlNode Serialize(object instance, Type? type = null)
else
{
XmlDocument context = new();
-
- // Use the "Type" attribute if generic or nested type as ` and + are not allowed as XML node names
- if (type.IsGenericType)
- {
- element = context.CreateElement("Generic");
- ((XmlElement)element).SetAttribute("Type", type.GetDisplayName().XMLEscape());
- }
- else if (type.IsNested)
- {
- element = context.CreateElement("Nested");
- ((XmlElement)element).SetAttribute("Type", type.GetDisplayName().XMLEscape());
- }
- else
- {
- element = context.CreateElement(type.GetDisplayName());
- }
-
+ element = context.CreateElement("Object");
+ ((XmlElement)element).SetAttribute("Type", type.GetDisplayName());
+
+ // Serialize fields and properties
this.SerializeMembers(instance, type).ForEach(pair => element.AppendChild(context.ImportNode(pair.Item1, true)));
}
@@ -273,11 +258,21 @@ public XmlNode Serialize(object instance, Type? type = null)
{
continue;
}
- XmlNode node = context.CreateElement(property.Name);
- this.Serialize(value, property.PropertyType).ChildNodes
+
+ XmlElement element = context.CreateElement(property.Name);
+
+ XmlNode serialized = this.Serialize(value, value.GetType());
+ string? typeAttribute = serialized.Attributes?["Type"]?.InnerText;
+ if (typeAttribute is not null)
+ {
+ element.SetAttribute("Type", typeAttribute);
+ }
+
+ serialized.ChildNodes
.Cast()
- .ForEach(child => node.AppendChild(context.ImportNode(child, true)));
- yield return (node, property);
+ .ForEach(child => element.AppendChild(context.ImportNode(child, true)));
+
+ yield return (element, property);
}
// Recursively serialize fields
@@ -288,11 +283,21 @@ public XmlNode Serialize(object instance, Type? type = null)
{
continue;
}
- XmlNode node= context.CreateElement(field.Name);
- this.Serialize(value, field.FieldType).ChildNodes
+
+ XmlElement element = context.CreateElement(field.Name);
+
+ XmlNode serialized = this.Serialize(value, value.GetType());
+ string? typeAttribute = serialized.Attributes?["Type"]?.InnerText;
+ if (typeAttribute is not null)
+ {
+ element.SetAttribute("Type", typeAttribute);
+ }
+
+ serialized.ChildNodes
.Cast()
- .ForEach(child => node.AppendChild(context.ImportNode(child, true)));
- yield return (node, field);
+ .ForEach(child => element.AppendChild(context.ImportNode(child, true)));
+
+ yield return (element, field);
}
}
@@ -320,7 +325,7 @@ public XmlNode Serialize(object instance, Type? type = null)
{
throw new SerializationException(child, $"Attempted to deserialize non-deserializable property {property.Name} in {type.GetDisplayName()}");
}
- deserialized.Add((this.Deserialize(child, property.PropertyType), property));
+ deserialized.Add((this.Deserialize(child, child.GetTypeToDeserialize() ?? property.PropertyType), property));
continue;
}
@@ -332,7 +337,7 @@ public XmlNode Serialize(object instance, Type? type = null)
{
throw new SerializationException(child, $"Attempted to deserialize non-deserializable field {field.Name} in {type.GetDisplayName()}");
}
- deserialized.Add((this.Deserialize(child, field.FieldType), field));
+ deserialized.Add((this.Deserialize(child, child.GetTypeToDeserialize() ?? field.FieldType), field));
continue;
}
@@ -345,7 +350,8 @@ public XmlNode Serialize(object instance, Type? type = null)
.Where(pair => pair.Item2 is not null && pair.Item2.Serializable)
.Select(pair => pair.member)
.ToArray();
- if (toDeserialize.Any() && !toDeserialize.All(deserialized.Select(pair => pair.Item2).Contains))
+ HashSet deserializedMembers = deserialized.Select(pair => pair.Item2).ToHashSet();
+ if (toDeserialize.Any() && !toDeserialize.All(deserializedMembers.Contains))
{
throw new SerializationException(node, $"One or more mandatory properties or fields of {type.GetDisplayName()} were not deserialized");
}
diff --git a/Serialization/Specialized/ArraySerializer.cs b/Serialization/Specialized/ArraySerializer.cs
index 29b6178..74e3821 100644
--- a/Serialization/Specialized/ArraySerializer.cs
+++ b/Serialization/Specialized/ArraySerializer.cs
@@ -39,7 +39,7 @@ public override XmlNode Serialize(object instance, Type? arrayType = null)
XmlDocument context = new();
XmlElement arrayElement = context.CreateElement("Array");
- arrayElement.SetAttribute("Type", $"{itemType.GetDisplayName().XMLEscape()}[]");
+ arrayElement.SetAttribute("Type", $"{itemType.GetDisplayName()}[]");
this.SerializeItems(instance, itemType).ForEach(node => arrayElement.AppendChild(context.ImportNode(node, true)));
return arrayElement;
}
diff --git a/Serialization/Specialized/CollectionSerializer.cs b/Serialization/Specialized/CollectionSerializer.cs
index 2f600ad..d49fdc7 100644
--- a/Serialization/Specialized/CollectionSerializer.cs
+++ b/Serialization/Specialized/CollectionSerializer.cs
@@ -50,7 +50,7 @@ public virtual XmlNode Serialize(object instance, Type? collectionType = null)
XmlDocument context = new();
XmlElement collectionElement = context.CreateElement("Collection");
- collectionElement.SetAttribute("Type", collectionType.GetDisplayName().XMLEscape());
+ collectionElement.SetAttribute("Type", collectionType.GetDisplayName());
this.SerializeItems(instance, itemType).ForEach(node => collectionElement.AppendChild(context.ImportNode(node, true)));
return collectionElement;
}
@@ -97,7 +97,7 @@ protected IEnumerable SerializeItems(object instance, Type itemType)
XmlElement itemElement = context.CreateElement("item");
if (item.GetType() != itemType)
{
- itemElement.SetAttribute("Type", item.GetType().GetDisplayName().XMLEscape());
+ itemElement.SetAttribute("Type", item.GetType().GetDisplayName());
}
this.ItemSerializer.Serialize(item, item.GetType()).ChildNodes
.Cast()
diff --git a/Serialization/Specialized/DictionarySerializer.cs b/Serialization/Specialized/DictionarySerializer.cs
index fabbced..7dc481a 100644
--- a/Serialization/Specialized/DictionarySerializer.cs
+++ b/Serialization/Specialized/DictionarySerializer.cs
@@ -50,7 +50,7 @@ public XmlNode Serialize(object instance, Type? dictionaryType = null)
XmlDocument context = new();
XmlElement dictionaryElement = context.CreateElement("Dictionary");
- dictionaryElement.SetAttribute("Type", dictionaryType.GetDisplayName().XMLEscape());
+ dictionaryElement.SetAttribute("Type", dictionaryType.GetDisplayName());
foreach (object item in (IEnumerable)instance)
{
@@ -60,7 +60,7 @@ public XmlNode Serialize(object instance, Type? dictionaryType = null)
XmlElement keyElement = context.CreateElement("key");
if (key.GetType() != keyType)
{
- keyElement.SetAttribute("Type", key.GetType().GetDisplayName().XMLEscape());
+ keyElement.SetAttribute("Type", key.GetType().GetDisplayName());
}
this.itemSerializer.Serialize(key, key.GetType()).ChildNodes
.Cast()
@@ -69,7 +69,7 @@ public XmlNode Serialize(object instance, Type? dictionaryType = null)
XmlElement valueElement = context.CreateElement("value");
if (value.GetType() != valueType)
{
- valueElement.SetAttribute("Type", value.GetType().GetDisplayName().XMLEscape());
+ valueElement.SetAttribute("Type", value.GetType().GetDisplayName());
}
this.itemSerializer.Serialize(value, value.GetType()).ChildNodes
.Cast()
diff --git a/Serialization/Specialized/EnumerableSerializer.cs b/Serialization/Specialized/EnumerableSerializer.cs
index 74b428e..08edc21 100644
--- a/Serialization/Specialized/EnumerableSerializer.cs
+++ b/Serialization/Specialized/EnumerableSerializer.cs
@@ -39,7 +39,7 @@ public override XmlNode Serialize(object instance, Type? enumerableType = null)
XmlDocument context = new();
XmlElement enumerableElement = context.CreateElement("Enumerable");
- enumerableElement.SetAttribute("Type", enumerableType.GetDisplayName().XMLEscape());
+ enumerableElement.SetAttribute("Type", enumerableType.GetDisplayName());
this.SerializeItems(instance, itemType).ForEach(node => enumerableElement.AppendChild(context.ImportNode(node, true)));
return enumerableElement;
}
diff --git a/Serialization/Specialized/NodeSerializer.cs b/Serialization/Specialized/NodeSerializer.cs
index 9fc58df..e638549 100644
--- a/Serialization/Specialized/NodeSerializer.cs
+++ b/Serialization/Specialized/NodeSerializer.cs
@@ -37,25 +37,10 @@ public override XmlNode Serialize(object instance, Type? nodeType = null)
XmlDocument context = new();
- // Use the "Type" attribute if generic or nested type as ` and + are not allowed as XML node names
- XmlElement element;
- if (nodeType.IsGenericType)
- {
- element = context.CreateElement("Generic");
- element.SetAttribute("Type", nodeType.GetDisplayName().XMLEscape());
- }
- else if (nodeType.IsNested)
- {
- element = context.CreateElement("Nested");
- element.SetAttribute("Type", nodeType.GetDisplayName().XMLEscape());
- }
- else
- {
- element = context.CreateElement(nodeType.GetDisplayName());
- }
-
- Serializer defaultSerializer = (Serializer)this.ItemSerializer;
+ XmlElement element = context.CreateElement("Node");
+ element.SetAttribute("Type", nodeType.GetDisplayName());
+ Serializer defaultSerializer = (Serializer)this.ItemSerializer;
defaultSerializer.SerializeMembers(nodeInstance, nodeType).ForEach(pair => element.AppendChild(context.ImportNode(pair.Item1, true)));
if (nodeInstance.GetChildCount() is 0)
@@ -90,7 +75,7 @@ public override object Deserialize(XmlNode node, Type? nodeType = null)
{
node.RemoveChild(childrenElement);
}
-
+
Serializer defaultSerializer = (Serializer)this.ItemSerializer;
object instance = Activator.CreateInstance(nodeType, true) ?? throw new SerializationException(node, $"Unable to instantiate {nodeType.GetDisplayName()}");