Sometime we need to work with xml files which schema is not static and can be changed in runtime. If schema is predefined we may define POC class, mark it with necessary Xml.. attributes (XmlRoot, XmlAttribute, XmlArray, etc.), deserialize data and process xml file in strongly typed way. However in order to work with extendable xml files in this way such approach can’t be used because in compile-time we don’t know what exact data will be in xml file.
However we still can work with such xml files in strongly typed way using C# dynamic objects with custom deserialization. Let’s consider the following example: suppose that we have the following xml defining some List entity (it is used from Sharepoint world, but exact area is not important here. It may be xml defining any entity):
In order to deserialize it and work with it in C# we create the following POC class:
In this POC class we defined properties for Title and Fields and mapped them on appropriate xml tags. FieldEntity class is shown below:
Now suppose that we need to add new data to xml file. If we would know what exact data will be added we of course could just add new properties to our POC class and use them with new xml. However we don’t know yet what exact data will be added, so we need to use more tricky approach with dynamic object. Let’s define Extension class which inherits DynamicObject and implement custom deserialization for it:
Custom deserialization (implementation of IXmlSerializable interface) is needed for making it possible to use any xml schema. And dynamic object is needed for possibility to work with deserialized objects in strongly typed way. Basically what happens here is that during deserialization we store whole XElement for our object in internal class variable and then in TryGetMember method (which comes from DynamicObject) map requested member name on xml tags, attributes and content.
Ok, now when we have dynamic object with custom xml deserialization we may extend our list POC with it:
Alternatively we could work without ListEntity at all by using only Extension object for anything, but I would like to show situation when we have some legacy code which already uses POC classes and which we need to extend. Having such C# part we may now add new data to xml and work with it in strongly typed way:
Here we added 2 extensions with own schema: one for UserCustomAction, another for Items. With our POC class we may work with it like this:
As you can see this approach allows us to work both with single objects and with collections of objects in strongly typed way. Hope that this information will help someone.