I have a ApplicationSettingsBase object I use to save user preferences, as well as application settings. For all of my built-in types, it properly serializes to XML and I get a nice user-editable config file. However, for my custom type "RuleCollection", this doesn't work, the only way for me to serialize it is binary which is nonsense to the user.
I have tried from the following links without success:
Add a collection of a custom class to Settings.Settings -- I originally was trying to serialize a CleanRule[] as I was able to serialize a string[] without issue. Adding the collection class as a wrapper was a band-aid that didn't work.
Custom Xml Serialization of Unknown Type and Implementing Custom XML Serialization/Deserialization of compound data type? -- I wasn't able to make settings.Save() trigger the custom XML Read/Write classes from implementing IXmlSerializable
, I think if I could force it to, this would work.
What I'm hoping for is a nice XML output where I have something like
-> Collection
-> Rule 1
-> Title
-> Description
-> Enabled
-> Mode
-> Regex
-> Args
-> Arg1
-> Arg2
-> Rule 2
-> Title
-> Description
-> Enabled
-> Mode
-> Regex
-> Args
-> Arg1
I am using .NET Framework 4.7.2
public class UserSettings : ApplicationSettingsBase
{
[UserScopedSetting]
[SettingsSerializeAs(SettingsSerializeAs.Binary)]
public RuleCollection Rules
{
get { return (RuleCollection)this["Rules"]; }
set { this["Rules"] = value; }
}
... //other properties
}
Below is the properties of the RuleCollection
and CleanRule
classes, CleanMode
is an `Enum
[Serializable]
[SettingsSerializeAs(SettingsSerializeAs.Xml)]
public class CleanRule
{
public string Title { get; private set; }
public string Description { get; private set; }
public bool Enabled { get; private set; } = true;
public CleanMode Mode { get; private set; }
public Regex R { get; private set; }
public string[] Args { get; private set; }
... //constructors and other methods
}
[Serializable]
[SettingsSerializeAs(SettingsSerializeAs.Xml)]
public class RuleCollection : IEnumerable<CleanRule>
{
public List<CleanRule> Rules { get; set; }
... // constructors and other methods
}
Finally, I am editing and saving the property like so
settings = new UserSettings();
settings.Rules = settings.Rules ?? new RuleCollection();
settings.Save();
and
RuleForm rf = new RuleForm(settings.Rules);
if(rf.ShowDialog(this) == DialogResult.OK)
{
settings.Rules = rf.Rules;
settings.Save();
}
EDIT: I've boiled this down to a more simple example EDIT 2: This example now works, it was missing a no-arg constructor as per How to serialize a class with a list of custom objects? My main code is still not working, but it would appear that serialization errors are being masked by the ApplicationSettingsBase class
public class UserSettings : ApplicationSettingsBase
{
[UserScopedSetting]
public Test Test
{
get { return (Test)this["Test"]; }
set { this["Test"] = value; }
}
}
[Serializable]
public class Test
{
public int I { get; set; }
public string S { get; set; }
public Test(){ }
public Test(int i, string s)
{
I = i;
S = s;
}
}
settings = new UserSettings();
settings.Test = new Test(30, "Tom");
settings.Save();
Result:
<setting name="Test" serializeAs="Xml">
<value>
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<I>30</I>
<S>Tom</S>
</Test>
</value>
</setting>