Serialize list of interfaces using XML Serialization

核能气质少年 提交于 2020-02-05 06:26:30

问题


I have the class below which I need to serialize using the XML Serializer

I know that the XML serializer does not like interfaces

However, our coding standards normally involve always coding to interfaces not concrete classes

I thought of a way to be able to stream this list without changing the types which would cause many compilation issues, as well as breaking our standards

My idea is to have a property which reads the Meters list and casts to concrete classes then to totally ignore meters when it comes to serializing

However, the XML will still need to have Meters as the element name

However this does not work

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.Xml.Serialization;

    public class MeterWalkOrder
    {
        public MeterWalkOrder()
        {
            Meters = new List<IMeter>();
        }

        public String Name { get; set; }


        [XmlIgnore]
        public List<IMeter> Meters { get; set; }

        [XmlArrayItem(ElementName = "Meter")]
        [XmlElement(ElementName = "Meters")]
        public List<Meter> SerializableMeters
        {
            get
            {
                return Meters.Cast<Meter>().ToList();
            }
            set
            {
                Meters = new List<IMeter>(value);                
            }
        }
    }
}

Is there any way around this?

My XML (which cannot be changed) is below

   <MeterWalkOrder>
      <Name>Red Route</Name>
      <Meters>
        <Meter>
          <MeterID>1</MeterID>
          <SerialNumber>12345</SerialNumber>
        </Meter>
        <Meter>
          <MeterID>2</MeterID>
          <SerialNumber>SE</SerialNumber>
        </Meter>
      </Meters>
    </MeterWalkOrder>

The top level error is

There was an error reflecting type 'WindowsFormsApplication1.Classes.MeterWalkOrder'.

The inner exception is

{"XmlElement, XmlText, and XmlAnyElement cannot be used in conjunction with XmlAttribute, XmlAnyAttribute, XmlArray, or XmlArrayItem."}

I really would like to avoid setting a precedent for using lists of concrete classes


回答1:


You will need to replace [XmlElement(ElementName = "Meters")] with [XmlArray(ElementName = "Meters")] as the error states:

{"XmlElement, XmlText, and XmlAnyElement cannot be used in conjunction with XmlAttribute, XmlAnyAttribute, XmlArray, or XmlArrayItem."}

To define an Array for the XmlSerializer you can mark it with XmlArray and its corresponding items with XmlArrayItem

Example:

public class MeterWalkOrder
{
    public MeterWalkOrder()
    {
        Meters = new List<IMeter>();
    }

    public String Name { get; set; }

    [XmlIgnore]
    public List<IMeter> Meters { get; set; }

    [XmlArrayItem(ElementName = "Meter")]
    [XmlArray(ElementName = "Meters")]
    public List<Meter> SerializableMeters
    {
        get
        {
            return Meters.Cast<Meter>().ToList();
        }
        set
        {
            Meters = new List<IMeter>(value);                
        }
    }
}

 public interface IMeter {
   int MeterID { get; set; }
 }

 public class Meter : IMeter {
     public int MeterID { get; set; }
     public string SerialNumber { get; set; }
 }

Test:

var data = new MeterWalkOrder{ Name = "Red Route", Meters = new List<IMeter>
{
     new Meter{ MeterID = 1, SerialNumber = "12345"},
     new Meter{ MeterID = 2, SerialNumber = "SE"}
}};
using (var stream = new FileStream("C:\\Users\\Adam\\Desktop\\Test2.xml", FileMode.OpenOrCreate))
{
    XmlSerializer ser = new XmlSerializer(typeof(MeterWalkOrder));
    ser.Serialize(stream, data);
}

Result:

<?xml version="1.0"?>
<MeterWalkOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>Red Route</Name>
  <Meters>
    <Meter>
      <MeterID>1</MeterID>
      <SerialNumber>12345</SerialNumber>
    </Meter>
    <Meter>
      <MeterID>2</MeterID>
      <SerialNumber>SE</SerialNumber>
    </Meter>
  </Meters>
</MeterWalkOrder>


来源:https://stackoverflow.com/questions/26172148/serialize-list-of-interfaces-using-xml-serialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!