I wonder how to implement the method ReadXml of the IXmlSerializable interface when my XML contains recursive tags like in the following example:
<?xml version='1.0' encoding='utf-8'?>
<dform>
<label name='label-a' text='A' dbpath='module/label-a'/>
<textmemo name='textmemo-a' text='' dbpath='module/textmemo-a'/>
<section name='section-a' text='' dbpath='module/section-a'>
<textmemo name='textmemo-b' text='' dbpath='module/textmemo-b'/>
</section>
<section name='section-b' text='' dbpath='module/section-b'>
<textmemo name='textmemo-c' text='' dbpath='module/textmemo-c'/>
<label name='label-c' text='A' dbpath='module/label-c'/>
<section name='section-c' text='' dbpath='module/section-c'>
<label name='label-d' text='A' dbpath='module/label-d'/>
</section>
</section>
</dform>
The element <section> works like a container for all kind of elements, itself included.
I need to translate this structure into objects: a List of elements (objects) that contains other List objects when the element is a Section. So I've created the following Interface and Classes:
public interface IWidget
{
String type { get;}
String name { get; set; }
String labelCation { get; set; }
String text { get; set; }
String dbpath { get; set; }
}
class Textmemo : IWidget
{
public String type { get; }
public String name { get; set; }
public String labelCation { get; set; }
public String text { get; set; }
public String dbpath { get; set; }
public List<IWidget> subsection { get; set; }
public Textmemo()
{
type = "CONTROL";
}
}
class Label : IWidget
{
public String type { get; }
public String name { get; set; }
public String labelCation { get; set; }
public String text { get; set; }
public String dbpath { get; set; }
public List<IWidget> subsection { get; set; }
public Label()
{
type = "LABEL";
}
}
class Section : IWidget
{
public String type { get; }
public String name { get; set; }
public String labelCation { get; set; }
public String text { get; set; }
public String dbpath { get; set; }
public List<IWidget> subsection { get; set; }
public Section()
{
type = "SECTION";
subsection = new List<IWidget>();
}
}
The Section class has one more property compared with the interface IWidget from which it inherits, that is the subsection property.
Then I was ready to move my steps starting from this example XmlSerializer serialize generic List of interface
but I really don't understand how to manage the <section> element in my code, that, at the moment, it is nothing more than the signature of the class:
public class WidgetsList: List<IWidget>, IXmlSerializable
{
public WidgetsList() : base() { }
public System.Xml.Schema.XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
}
public void WriteXml(XmlWriter writer)
{
}
}
Thanks a lot for the advice!
Why are you wanting to implement
IXmlSerializableyourself? You can use various attributes to have the framework do this for you. For example, define a base class (given all your implementations are the same):The attributes here specify that
typeandlabelCationare ignored (as they don't exist in the XML). The rest are mapped to XML attributes (e.g.name='abc').You can then create your three sub-types:
Sectionis the interesting one as it defines the types permitted as child elements with the relevant name mappings. Similarly to this, you'd then define the root element:You can see in this demo that your XML round-tripped through the serializer is the same, thus proving this works.