Сериализация вложенного списка в С# в XML

У меня есть вложенный список в С#: List<List<OVReady.Types.PointF[]>>, и его нужно сериализовать в xml

Мой код:

[XmlRoot("AlertInfo")]
public class AlertInfo
{
    [XmlElement("TargetID")]
    public string strTargetId { get; set; }

    [XmlElement("ChannelID")]
    public string strChId { get; set; }

    [XmlElement("Timestamp")]
    public string strTimestamp { get; set; }

    [XmlElement("Object")]
    public RectObject rfObject { get; set; }

    [XmlArray("Polygons")]
    [XmlArrayItem("Polygon")]
    public List<List<OVReady.Types.PointF[]>> lstPolygons { get; set; }
}

public class RectObject
{
    [XmlAttribute("x")]
    public float x { get; set; }
    [XmlAttribute("y")]
    public float y { get; set; }
    [XmlAttribute("width")]
    public float width { get; set; }
    [XmlAttribute("height")]
    public float height { get; set; }
}

Что я получаю:

<AlertInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TargetID>730</TargetID>
  <ChannelID>613</ChannelID>
  <Timestamp>2014-09-26 19:56:07:5660</Timestamp>
  <Object x="0.24375" y="0.025" width="0.259375" height="0.9375001" />
  <Polygons>
    <Polygon>
      <ArrayOfPointF>
        <PointF>
          <X xmlns="http://www.objectvideo.com/schemas/ovready">0.30625</X>
          <Y xmlns="http://www.objectvideo.com/schemas/ovready">0.9375</Y>
        </PointF>
        <PointF>
          <X xmlns="http://www.objectvideo.com/schemas/ovready">0.696875</X>
          <Y xmlns="http://www.objectvideo.com/schemas/ovready">0.9416667</Y>
        </PointF>
      </ArrayOfPointF>
    </Polygon>
  </Polygons>
</AlertInfo>

Что я хочу:

<AlertInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TargetID>730</TargetID>
  <ChannelID>613</ChannelID>
  <Timestamp>2014-09-26 19:56:07:5660</Timestamp>
  <Object x="0.24375" y="0.025" width="0.259375" height="0.9375001" />
  <Polygons>
    <Polygon>
        <Point x=0.30625 y=0.9375>
        <Point x=0.696875 y=0.9416667>
      </Polygon>
  </Polygons>
</AlertInfo>

Как я могу удалить тег и установить положение x и y, как я хочу?


person currarpickt    schedule 26.09.2014    source источник
comment
Для этого вам необходимо реализовать методы Serialize и Deserialize в классе AlertInfo.   -  person Waqas Raja    schedule 26.09.2014
comment
Вы можете реализовать IXmlSerializable и обрабатывать сериализацию и десериализацию в методах ReadXml и WriteXml.   -  person juharr    schedule 26.09.2014
comment
Хорошие моменты от juharr. Я не думаю, что вы можете справиться с этим только с помощью атрибутов. Для правильной реализации IXmlSerializable проверьте: codeproject.com/Articles/43237 /   -  person Faris Zacina    schedule 26.09.2014
comment
Другой вариант — создать свои собственные классы Polygon и Point.   -  person juharr    schedule 26.09.2014


Ответы (2)


Начнем с самого простого возможного подхода. Редизайн вашей собственности, чтобы упростить сериализацию.

Чтобы добиться этого, мне пришлось ввести новый класс Polygon:

public class Polygon
{
    [XmlElement("Point")]
    public List<PointF> Points { get; set; }
}

И тогда вам придется перепроектировать свою собственность, чтобы она была:

[XmlArray("Polygons")]
[XmlArrayItem("Polygon")]
public List<Polygon> lstPolygons { get; set; }

Если вы не можете позволить себе роскошь изменить дизайн этого свойства, как в этом примере, ниже вы можете найти хак, который также может сработать. Это не для очистки, но это работает, и это просто.

Идея состоит в том, чтобы XmlIgnore ваш текущий атрибут, чтобы препятствовать его обработке XML-сериализатором, а затем использовать один дополнительный геттер, предназначенный только для сериализации, который динамически переформатирует данные с помощью LINQ, чтобы подготовить их для сериализатора. Проверьте код:

[XmlRoot("AlertInfo")]
public class AlertInfo
{
    [XmlElement("TargetID")]
    public string strTargetId { get; set; }

    [XmlElement("ChannelID")]
    public string strChId { get; set; }

    [XmlElement("Timestamp")]
    public string strTimestamp { get; set; }

    [XmlElement("Object")]
    public RectObject rfObject { get; set; }

    [XmlIgnore]
    public List<List<PointF[]>> lstPolygons { get; set; }

    [XmlArray("Polygons")]
    [XmlArrayItem("Polygon")]
    public List<Polygon> Polygons
    {
        get {
            return lstPolygons.Select(p => new Polygon() { Points = p.SelectMany(lp => lp).ToList() }).ToList();
        }
    }
}

Результат сериализации вышеуказанного свойства AlertInfo Polygons таков:

<Polygons>
  <Polygon>
    <Point x="0" y="0" />
    <Point x="0" y="0" />
  </Polygon>
</Polygons>

Альтернативный подход заключается в реализации IXmlSerializable и самостоятельном управлении сериализацией. О том, как это сделать, читайте в этой статье:

http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly

person Faris Zacina    schedule 26.09.2014
comment
Работал отлично для меня! Спасибо - person Dom; 26.11.2018

  1. Вы слишком много вложили, удалите самый вложенный массив:

    public List<List<OVReady.Types.PointF[]>> lstPolygons { get; set; }
    

    to

    public List<List<OVReady.Types.PointF>> lstPolygons { get; set; }
    
    • if you can modify OVReady.Types.PointF class than decorate it to proper serialize its properties to the attributes instead of the new elements
    • если нет, следуйте этому ответу
person Aik    schedule 26.09.2014