Как установить имя элемента XmlArrayItem для реализации List <Custom>? - PullRequest
17 голосов
/ 24 ноября 2011

Я хочу создать собственную структуру XML следующим образом:

<Hotels>
    <Hotel />
</Hotels>

Я создал реализацию List только для того, чтобы сделать это. Мой код выглядит следующим образом:

[XmlRootAttribute(ElementName="Hotels")]
public class HotelList: List<HotelBasic>

Поскольку класс, который содержит List, не называется Hotel, а HotelBasic, мой xml похож на

<Hotels>
   <HotelBasic />
</Hotels>

Как это исправить, не используя ISerializable или IEnumerable?

Ответы [ 3 ]

26 голосов
/ 24 ноября 2011
[XmlArray("Hotels")]
[XmlArrayItem(typeof(Hotel), ElementName="Hotel")]
public HotelList[] Messages { get; set; }

должен производить:

<Hotels>
    <Hotel />
    <Hotel />
</Hotels>

[XmlRoot("Hotels")]
public class HotelList : IXmlSerializable
{
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        this.Hotels = XDocument.Load(reader)
                               .Select(h => new Hotel { Name = (string)h.Attribute("name") }
                               .ToList();
    }

    public void WriteXml(XmlWriter writer)
    {
        throw new NotSupportedException();
    }
}
17 голосов
/ 24 ноября 2011

Если вы используете XmlSerializer, если все, что вам нужно сделать, это изменить способ сериализации вашего класса HotelBasic, вы можете использовать XmlTypeAttribute:

[XmlType(TypeName = "Hotel")]
public class HotelBasic
{
    public string Name { get; set; }
}

При использовании с вашим классом HotelList он будет сериализован как:

<Hotels xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Hotel>
    <Name>One</Name>
  </Hotel>
  <Hotel>
    <Name>Two</Name>
  </Hotel>
</Hotels>
7 голосов
/ 24 ноября 2011

Я думаю, что madd0 показывает самый простой вариант для вас здесь, но только для полноты ... лично я не рекомендую «сериализовать список как корневой объект» - по разным причинам (в том числе: я видел эти атрибутыне работает, по крайней мере, на платформе - возможно, это CF или SL, не помню).Вместо этого я всегда советую использовать пользовательский тип корня:

[XmlRoot("Hotels")]
public class HotelResult // or something similar
{
    [XmlElement("Hotel")]
    public List<HotelBasic> Hotels { get { return hotel; } }

    private readonly List<HotelBasic> hotels = new List<HotelBasic>();
}

Это будет иметь ту же структуру XML и обеспечивает большую гибкость (вы можете добавлять другие атрибуты / элементы в корень) и не выпекатьList<T> в вашу модель типов (предпочитайте инкапсуляцию, а не наследование и т. Д.).

...