Reputation: 155
I have a custom Option class that holds objects, with some additional parameters (name, info...). I'm trying to serialize a list of Option in order to save settings. All value types, and custom serializable classes seem to work fine, but a List doesn't deserialize properly. All i get is a System.Xml.XmlNode instead of List. The node contains the values from the list, they simply are not in a list.
Here is the relevant part of the Option class :
#region DefaultValue
private object _defaultObject = null;
[SettingsSerializeAs(System.Configuration.SettingsSerializeAs.Binary)]
public object DefaultValue
{
get { return _defaultObject; }
set
{
_defaultObject = value;
NotifyPropertyChanged("DefaultValue");
}
}
#endregion
#region Value
private object _object = null;
[SettingsSerializeAs(System.Configuration.SettingsSerializeAs.Binary)]
public object Value
{
get { return _object; }
set
{
if (DefaultValue == null)
{
DefaultValue = value;
_object = value;
NotifyPropertyChanged("Value");
}
else if (DefaultValue.GetType().IsAssignableFrom(value.GetType()))
{
_object = value;
NotifyPropertyChanged("Value");
}
}
}
Here is how i add the List to a List (the second one is for comparison, and works fine without the first) :
Add(new Option() { Name = "ModuleFolders", DisplayName = "Module folders", Value = new List<String>() { ".\\Modules", "..\\Modules" }, Group = "Session", Info = "This is the list of folders containing all of the modules", ShortInfo = "Paths to the module folders"});
Add(new Option() { Name = "ModulePattern", DisplayName = "Module pattern", Value = "GAME.Modules.*.dll", Group = "Session", Info = "This is the pattern used to find module assemblies by file name", ShortInfo = "Pattern for module names", IsReadOnly = true});
And finally, here is the resulting xml :
<?xml version="1.0"?>
<ArrayOfOption xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Option>
<DefaultValue xsi:type="ArrayOfString">
<string>.\Modules</string>
<string>..\Modules</string>
</DefaultValue>
<Value xsi:type="ArrayOfString">
<string>.\Modules</string>
<string>..\Modules</string>
</Value>
<Name>ModuleFolders</Name>
<DisplayName>Module folders</DisplayName>
<ShortInfo>Paths to the module folders</ShortInfo>
<Info>This is the list of folders containing all of the modules</Info>
<Group>Session</Group>
<IsReadOnly>false</IsReadOnly>
</Option>
<Option>
<DefaultValue xsi:type="xsd:string">GAME.Modules.*.dll</DefaultValue>
<Value xsi:type="xsd:string">GAME.Modules.*.dll</Value>
<Name>ModulePattern</Name>
<DisplayName>Module pattern</DisplayName>
<ShortInfo>Pattern for module names</ShortInfo>
<Info>This is the pattern used to find module assemblies by file name</Info>
<Group>Session</Group>
<IsReadOnly>true</IsReadOnly>
</Option>
</ArrayOfOption>
I can't find why the serializer isn't converting back the list properly. There is no error message either.
If needed, here is the GitHub link to the project.
Upvotes: 0
Views: 846
Reputation: 155
After lots of searching and experimenting i found an answer, so i'm putting it here in case someone else has the same problem :
XMLSerializer
to serialize/deserialize objects, but when errors happened, there was only a line on the output saying something went wrong, which wasn't very helpful.DataContractSerializer
, which gave me more information on what was going on.Turns out, for unknown types, such as List<String>
(weirdly enough, MSDN says it is a known type), one has to provide the type to the serializer AND the deserializer.
With DataContractSerializer
, it's done by adding [KnownType(typeof(List<String>))]
to the definition of the object using it.
In my case, this is how my class begins :
[Serializable]
[DataContract]
[KnownType(typeof(List<String>))]
[KnownType(typeof(DoubleInterval))]
public class Option : IOption
{
}
The DataContractSerializer
will use the attributes to map out objects to the XML data.
Upvotes: 1