Andrew Connell
Andrew Connell

Reputation: 5307

Deserialize generic collections - coming up empty

I've got a settings object for my app that has two collections in it. The collections are simple List generics that contain a collection of property bags. When I serialize it, everything is saved with no problem:

XmlSerializer x = new XmlSerializer(settings.GetType());
TextWriter tw = new StreamWriter(@"c:\temp\settings.cpt");
x.Serialize(tw, settings);

However when I deserialize it, everything is restored except for the two collections (verified by setting a breakpoint on the setters:

XmlSerializer x = new XmlSerializer(typeof(CourseSettings));
XmlReader tr = XmlReader.Create(@"c:\temp\settings.cpt");
this.DataContext = (CourseSettings)x.Deserialize(tr);

What would cause this? Everything is pretty vanilla... here's a snippet from the settings object... omitting most of it. The PresentationSourceDirectory works just fine, but the PresentationModules' setter isn't hit:

private string _presentationSourceDirectory = string.Empty;
public string PresentationSourceDirectory {
  get { return _presentationSourceDirectory; }
  set {
    if (_presentationSourceDirectory != value) {
      OnPropertyChanged("PresentationSourceDirectory");
      _presentationSourceDirectory = value;
    }
  }
}

private List<Module> _presentationModules = new List<Module>();
public List<Module> PresentationModules {
  get {
    var sortedModules = from m in _presentationModules
                        orderby m.ModuleOrder
                        select m;
    return sortedModules.ToList<Module>();
  }
  set {
    if (_presentationModules != value) {
      _presentationModules = value;
      OnPropertyChanged("PresentationModules");
    }
  }
}

Upvotes: 3

Views: 977

Answers (2)

chriszero
chriszero

Reputation: 1341

If a list is deserialized, the setter is never called. Just the getter. The Deserializer just invokes the #Add() method and adds the serialized elements to the exising List. This is behaviour by Design. See MSDN.
You could add a new property wich gets your list without any linq statements. Add an [XmlIgnore] to your existing property, the XmlSerializer will skip this property now.

[XmlIgnore]
public List<Module> PresentationModules {

Create a new property which exposes the list:

private List<Module> _presentationModules = new List<Module>();
public List<Module> PresentationModulesList {
  get { return _presentationModules; }
}

Your event in the setter of PresentationModules will only be invoked if you assign a NEW list to the property. Maybe you should make the setter private.

Upvotes: 1

gsiener
gsiener

Reputation: 883

You can override the serialization and de-serialization methods to add custom information. It's been awhile since I implemented something like this, but I recall having to override to reconstruct some private members from the object upon receiving the serialization data.

Upvotes: 0

Related Questions