1

I'm supporting a legacy, internal API that uses two classes that are serialized using XML. Both classes are sub-classes of a common base class:

namespace My.Namespace {

    [
        Serializable,
        XmlInclude(typeof(SubClassA)),
        XmlInclude(typeof(SubClassB)),
    ]
    public abstract class BaseClass {
        // etc.
    }

    [
        Serializable,
        XmlType(TypeName="My.Namespace.SubClassA"),
    ]
    public sealed class SubClassA: BaseClass {
        // etc.
    }

    [
        Serializable,
        XmlType(TypeName="My.Namespace.SubClassB"),
    ]
    public sealed class SubClassB: BaseClass {
        // etc.
    }
}

So far, so good.

However, the two sub-classes have now been refactored into a single new class (the differences between them are minimal), called SubClass, which also extends BaseClass.

The issue now is that the new class needs to be capable of deserializing legacy XML files that define instances of SubClassA and SubClassB. The problem is that there is no apparent relationship between these types and the new SubClass type. (The SubClassA and SubClassB classes are no longer part of the API and cannot be used to deserialize these instances.)

How do I configure BaseClass and SubClass so that newly serialized XML files define instances of SubClass definitions, while also being able to deserialize legacy XML file instances of SubClassA and SubClassB definitions into instances of SubClass? Can I make SubClassA and SubClassB aliases for SubClass when deserializing XML files?

(Let's assume that the serialized properties are common to SubClass, SubClassA and SubClassB.)

1 Answer 1

0

I don't think that the standard XmlSerializer provides the features you need. There may be third-party libraries exists that do, but I don't know of any.

I see the following possible approaches here:

  • Manual mapping at the XML-level: use XDocument to open the old-version XML and manipulate elements via the XML DOM. Modify the XML so that it becomes a valid XML for the new version of your type. Then use the XmlSerializer to deserialize the migrated XML with new-version datatypes.
  • Manual mapping at the DTO-level: Store the old datatypes in a separate assembly. Use extern aliases (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/extern-alias) in case of type name conflicts. Then deserialize the old-version XML into the old-version datatypes. Then manually map the data to the new datatypes. Finally, you can use the objects from the previous step "as is" or serialize them to XML and use such a new-version XML in the future processing.
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the suggestions, @serg. The first option you suggest is what I'm trying to avoid: I have a large number of legacy XML files within the company that need to be supported "as-is". As a last resort, that's certainly an option, but it's not an attractive one. :-) I don't think the second option is feasible, as we don't want to require a library dependency upon on an older version of itself. Unless someone can suggest otherwise, it's looking like the only non-hideous option being to retain both SubClassA and SubClassB as sub-classes of SubClass. :-(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.