1

I have a class which contain an interface member variable.How can i deserialize this class

interface ISensor { }

[Serializable]
class Sensor: ISensor { }

[Serializable]
class Root
{
    [XmlElement("Sensor")]
    public List<ISensor> SensorList{ get; set; }
}

My XML will be like this

  <?xml version="1.0" encoding="us-ascii"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Sensor >
        <SensorName>Name1</SensorName>
        <SensorValue>0.0</SensorValue>
    </Sensor>
    <Sensor>
        <SensorName>Name2</SensorName>
        <SensorValue>148.00</SensorValue>
    </Sensor>
</Root>
Prasanth V J
  • 1,126
  • 14
  • 32

1 Answers1

1

Assuming you are using XmlSerializer, there are two changes required for both serialization and deserialization:

  1. Tell the serializer the list of types that can appear, in other words the types that inherit from Sensor.
  2. Use a class for the List rather than an interface, in other words replace List<ISensor> with List<Sensor>.

Unfortunately, the XmlSerializer does not handle interfaces in the way you want. See XmlSerializer serialize generic List of interface for more information.

If using a base class is not an option You could write your own XML serializer by implementing IXmlSerializable. Override ReadXml and parse the XML manually.

For example:

public interface ISensor { }

[Serializable]
public class Sensor : ISensor { }

[Serializable]
public class Root
{
    // Changed List<ISensor> to List<Sensor>. I also changed
    // XmlElement to XmlArray so it would appear around the list.       
    [XmlArray("Sensor")]
    public List<Sensor> SensorList { get; set; }
}

[Serializable]
public class SensorA : Sensor
{
    [XmlElement("A")]
    public string A { get; set; }
}

[Serializable]
public class SensorB : Sensor
{
    [XmlElement("B")]
    public string B { get; set; }
}

class Program
{
    public static void Main(string[] args)
    {
        XmlSerializer xmlSerializer;

        Root root = new Root();
        root.SensorList = new List<Sensor>();
        root.SensorList.Add(new SensorA() {A = "foo"});
        root.SensorList.Add(new SensorB() {B = "bar"});

        // Tell the serializer about derived types
        xmlSerializer = new XmlSerializer(typeof (Root), 
            new Type[]{typeof (SensorA), typeof(SensorB)});
        StringBuilder stringBuilder = new StringBuilder();
        using (StringWriter stringWriter = new StringWriter(stringBuilder))
        {
            xmlSerializer.Serialize(stringWriter, root);
        }

        // Output the serialized XML
        Console.WriteLine(stringBuilder.ToString());

        Root root2;
        using (StringReader stringReader = new StringReader(stringBuilder.ToString()))
        {
            root2 = (Root) xmlSerializer.Deserialize(stringReader);
        }
    }
}

The output from the Console.WriteLine statement is:

<?xml version="1.0" encoding="utf-16"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Sensor>
    <Sensor xsi:type="SensorA">
      <A>foo</A>
    </Sensor>
    <Sensor xsi:type="SensorB">
      <B>bar</B>
    </Sensor>
  </Sensor>
</Root>
Community
  • 1
  • 1
akton
  • 14,148
  • 3
  • 43
  • 47
  • How can i do the deserialization – Prasanth V J Jan 01 '13 at 08:16
  • I have updated the answer and example to talk about deserialization, although the changes required are the same. Is there anything you needed specifically? – akton Jan 01 '13 at 08:31
  • 1
    For my case i will not be able to change the format of the XML(Check the XML in the question).I need to deserialize that XMl. – Prasanth V J Jan 01 '13 at 09:00
  • Is there any way to specify that to be loaded to class SensorA.In java there is an option to specify it. [serializerObj.alias("Sensor", SensorA.class);]Is there anything similar in C# – Prasanth V J Jan 01 '13 at 09:17
  • Can you update the question with the format of the contents of the `Sensor` element, please? Without it, it will be hard to determine exactly how to deserialize the XML. – akton Jan 01 '13 at 09:26
  • I get this XML from different ipbased hardware controllers.The schema of the XMl will be same in all controllers.But depending on the controller i have to load sensor to different classes which are derived from ISensor. – Prasanth V J Jan 01 '13 at 09:52
  • Given that the name of the sensor is embedded in XML within the `Sensor` XML, you will need to override IXmlSerialzable in Root and implement ReadXml. The default XmlSerializer relies on XmlElement names or attributes to determine the serialization types. – akton Jan 01 '13 at 09:59