8

I have a class that is serialized into/deserialized from XML and stored in/restored from a file:

public class Customer
{
    public string FirstName;
    public string LastName;

    public Customer()
    {
    }

    public Customer(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }

    public static Customer Load(TextReader reader)
    {
        XmlSerializer deserializer = new XmlSerializer(typeof(Customer));
        return (Customer)deserializer.Deserialize(reader);
    }

    public void Save(TextWriter writer)
    {
        XmlSerializer serializer = new XmlSerializer(GetType());
        serializer.Serialize(writer, this);
    }
}

In a newer version of this class I added a new property

public string MiddleName;

It is a common use case that a user has installed both the old and new version of my program. They both read and write the same serialized file. When the new version writes the file, all three properties (FirstName, LastName, MiddleName) are written. The old program reads the file but omits the unknown element MiddleName. It saves the file without MiddleName, so it's value is lost for the newer program.

Is there a way to store the original XML when deserializing and 'merge' the unknown elements back in when serializing? The old program would ignore unknown elements but write them back into the file so they are not lost for the new program.

floppes
  • 461
  • 3
  • 10
  • 2
    Not with the xmlserializer, no. How would the xmlserializer know what are unknown fields for him – Icepickle Jan 14 '16 at 10:43
  • Introduce `Version` property to serialized object **early**. When old version tries to read xml from new - you should throw "Unknown version" exception (or, if you prefer, deserialize it and set flag somewhere to **not** serialize changes, thus not overwriting original file and loosing uknown properties values). The new version in turn will be able to do something to support *backward compatibility* (e.g. set values of new properties of object depending on the version). – Sinatr Jan 14 '16 at 11:05
  • This is possible if you implement [the IXmlSerializable interface](https://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable%28v=vs.110%29.aspx) on your data classes, then you can fully control the serialization process. I have done something very similar where the original XML was kept as part of a data entity once the XML had been deserialized, but assigning it to the property was done immediately after the deserialization call. – slugster Jan 14 '16 at 11:33
  • @Icepickle Your answer is slightly incorrect - it is available with the XmlSerializer but only if you implement IXmlSerializable. – slugster Jan 14 '16 at 11:37
  • @slugster I assumed that he would have no way to update the classes for his old program, in which way it wouldn't be possible, but thanks for the update :) – Icepickle Jan 14 '16 at 17:42
  • @Icepickle You have a good point there :) – slugster Jan 14 '16 at 22:10
  • @floppes Who would you updated your old program with the selected answer in your case? – Icepickle Jan 15 '16 at 14:57
  • I have no chance to update the old program, it is already out in the field. Therefore the new program will use another file to store the XML. But for the future the new program gets the XmlAnyElement entry to stay compatible for future changes. – floppes Jan 15 '16 at 15:24

2 Answers2

12

Can't test it right now as I'm on Mac OS X, but XmlAnyElement should work:

[XmlAnyElement]
public XmlElement[] Unsupported { get; set; }
Gene
  • 4,192
  • 5
  • 32
  • 56
-1

XMLSerializer serializes. If the info is not available how could it serialize that?

What you could do is update the xmlfile, instead of serializing and overwriting it. It is extra work because you will have to traverse the file yourself but it allows you to achieve what you want.

How To Modify and Save XML with the XmlDocument Class in the .NET Framework SDK

Jef Patat
  • 999
  • 1
  • 10
  • 26