I have an object model which I need to serialize as XML in order to save the state to a text file. I'm mostly happy with how this is working but I'm stuck trying to serialize an ObservableCollection of ModelRun where ModelRun has several derived types that can be introduced as a result of plug ins (so can't be known at design time).
Here is the code I use to serialize it (this is in an implementation of an interface so has IXmlSerializable implemented - this code is in the WriteXml override):-
if (property.Name == "ModelRuns" || property.Name == "SavedModelRnuns")
{
writer.WriteStartElement(property.Name);
writer.WriteAttributeString("type", property.GetValue(this).GetType().FullName);
XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<ModelRun>));
serializer.Serialize(writer, property.GetValue(this));
writer.WriteEndElement();
}
Here's a Model Run (simplified)
public class ModelRun : INotifyPropertyChanged
{
public ModelRun()
{ }
}
and a typical derived model run (simplified)
public class ScenarioModelRun : ModelRun
{
public ScenarioConfiguration ScenarioConfiguration { get; set; }
}
Here is the property ModelRuns (n.b. although this is virtual it hasn't been overridden, I want that to be an option for future plugins though):-
private ObservableCollection<ModelRun> mModelRuns;
public virtual ObservableCollection<ModelRun> ModelRuns
{
get { return mModelRuns; }
set { mModelRuns = value; ModelRunsUpdated?.Invoke(this, EventArgs.Empty); }
}
When I call serializer.Serialize I get an error message:- The type ScenarioModelRun may not be used in this context. To use ScenarioModelRun as a parameter, return type, or member of a class or struct, the parameter, return type, or member must be declared as type ScenarioModelRun (it cannot be object). Objects of type ScenarioModelRun may not be used in un-typed collections, such as ArrayLists.
I've tried implementing IXmlSerializable in ScenarioModelRun, same as I did with the interface implementation above but that hasn't worked. Indeed, the WriteXml method never even got called so my guess is that the error comes back as a result of the serializer not even being able to build the collection.
I've tried adding a reference to my initial plugin project (this won't be an option in the future but thought it was worth a try while I was investigating) so that I can refer to its types and pass those into the serializer:-
XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<ModelRun>), new Type[] { typeof(ScenarioModelRun), typeof(ObservableCollection<ScenarioModelRun>) });
this didn't work either
Any suggestions as to how I should handle this? I thought implementing IXmlSerializable was probably the best way as that allows the consuming class to not know about plugged in types but that's not even resulting in WriteXML getting called so that doesn't help.