【问题标题】:Serialize list of interfaces using XML Serialization使用 XML 序列化序列化接口列表
【发布时间】:2014-10-03 10:56:16
【问题描述】:

我有下面的类,我需要使用 XML 序列化器对其进行序列化

我知道 XML 序列化器不喜欢接口

但是,我们的编码标准通常总是涉及对接口而不是具体类的编码

我想了一种方法,可以在不更改会导致许多编译问题以及违反我们标准的类型的情况下流式传输此列表

我的想法是有一个属性来读取 Meters 列表并转换为具体的类,然后在序列化时完全忽略 Meters

但是,XML 仍然需要将 Meters 作为元素名称

但是这不起作用

    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);                
            }
        }
    }
}

有没有办法解决这个问题?

我的 XML(不能更改)在下面

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

顶级错误是

反映类型“WindowsFormsApplication1.Classes.MeterWalkOrder”时出现错误。

内部异常是

{"XmlElement、XmlText 和 XmlAnyElement 不能与 XmlAttribute、XmlAnyAttribute、XmlArray 或 XmlArrayItem 一起使用。"}

我真的很想避免开创使用具体类列表的先例

【问题讨论】:

  • [XmlElement(ElementName = "Meters")] 换成[XmlArray(ElementName = "Meters")]

标签: c# interface xml-serialization


【解决方案1】:

您需要将[XmlElement(ElementName = "Meters")] 替换为[XmlArray(ElementName = "Meters")],因为错误状态:

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

要为XmlSerializer 定义一个数组,您可以用XmlArray 标记它,并用XmlArrayItem 标记它的对应项

例子:

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; }
 }

测试:

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);
}

结果:

<?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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多