views:

461

answers:

3

We use xml serialization / deserialization extensively in our project to pass data between multiple application. We have a common xsd that we generate c# classes from then use XmlSerializer to go from xml to objects and back.

The problem we are having is when one app is updated to add new enum values but the other app is not updated yet. Now the app that is not updated tries to deserialize the xml and fails because it doesn't know about the new enum.

If we have app1 and app2, things are working correctly in the field, then app2 is update with a new enum value in the xsd and updated to the client in the field. Suddenly app1 breaks because it doesn't know about the enum, app1 might not even use that enum field, has not effect on app1, but it still breaks.

Are there any known ways around this. Basically what i want to do is define what do do when an enum is not found, use a default value or if the enum as a nullible type and set it to null.

Both XmlSerializer and DataContractSerializer throw exceptions is this situation.

I've looked at the custom xml serialization project YAXLib (http://www.codeproject.com/KB/XML/yaxlib.aspx) this also throws an exception but there is source code and can be changed. This project use different property attributes and would require quite a bit of change but is probably doable.

Any other suggestions.

A: 

use c# custom serialization with versioning of the objects; this would allow you to handle the various situations that arise when one app is updated and the other isn't

Aaron Saunders
Please elaborate on what you mean by "custom serialization". You might also say why it's "C# custom serialization", since the C# programming language does not have serialization in it.
John Saunders
+1  A: 

Unfortunately there's no way to control how enum values are deserialized... As a workaround, you could serialize the enum values as string :

[XmlIgnore]
public MyEnum MyProperty { get; set; }

[XmlElement("MyProperty")]
public string MyPropertyAsString
{
    get
    {
        return EnumToString(MyProperty);
    }
    set
    {
        MyProperty = StringToEnum<MyEnum>(value);
    }
}

public T StringToEnum<T>(string stringValue)
{
    // Manually convert the string to enum, ignoring unknown values
}

public string EnumToString<T>(T enumValue)
{
    // Convert the enum to a string
}
Thomas Levesque
no! you can tell the (de)serializer to ignore unknown fields
Itay
@Itay: We're not talking about unknown fields here (you can handle them with XmlAnyElement or XmlAnyAttribute), we're talking about unknown enum values...
Thomas Levesque
+1  A: 

You can make the producing application aware of the multiple versions of the consuming applications and have it use different namespaces, both XML and C#, for each of the versions. There needs to be some coordination up front between the applications to agree on which schema they will be following and there isadditional responsibility on the producing application to continue to be backward compatible with all possible active consumer applications.

GBegen