Как создать класс для XML Serializer - PullRequest
1 голос
/ 01 октября 2009

У меня есть следующий формат xml:

<FavouriteSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Customer>
    <ID>12</ID>
    <ID>2</ID>
    <ID>5</ID>
  </Customer>

  <Supplier>
    <ID>158</ID>
    <ID>23</ID>
    <ID>598</ID>
  </Supplier>
</FavouriteSettings>

=============================================== ==============
У меня будет класс, как показано ниже

class FavouriteList
{
   public string Name; // this name will be "Customer" and "Supplier"
   public List<int> aList; // to store those "ID" value
}

Class FavouriteSettings
{
   public List<FavouriteList> bigList;
}

Что мне нужно сделать или изменить, чтобы этот класс работал с XMLSerializer для генерации XML-файла подобного формата и десериализации обратно в список и класс как FavouriteList?

Ответы [ 5 ]

3 голосов
/ 01 октября 2009

XmlSerializer предназначен для очень прямого перевода ваших объектов в xml; Вы можете использовать IXmlSerializable, но это того не стоит. Вы бы лучше создавали объекты, которые отражают структуру xml. Или проще - используйте xsd, чтобы сделать это за вас:

xsd example.xml
xsd example.xsd /classes

Или Я подозреваю, следующее будет работать (не проверено) :

using System.Collections.Generic;
using System.Xml.Serialization;
public class FavoriteSettings
{
    [XmlArray("Customer")]
    [XmlArrayItem("ID")]
    public List<int> Customers { get; set; }

    [XmlArray("Supplier")]
    [XmlArrayItem("ID")]
    public List<int> Suppliers { get; set; }
}

В частности; если вы хотите, чтобы имена элементов («Заказчик» и т. д.) варьировались в зависимости от данных («Имя» и т. д.), то это не произойдет, если вы не используете IXmlSerializable или не напишете его самостоятельно с помощью XDocument (или аналогичный). Для простых данных, подобных этой, может быть XDocument является приемлемым вариантом? Но тогда вы делаете много дополнительной работы, особенно во время десериализации.


Вот пример использования вашего существующего класса через LINQ-to-XML:

static class Program
{
    static void Main() {
        var favs = new FavouriteSettings
        {
            bigList = new List<FavouriteList>
            {
                new FavouriteList {
                    Name = "Customer",
                    aList = new List<int>{
                        12,2,5
                    }
                }, new FavouriteList {
                    Name = "Supplier",
                    aList = new List<int>{
                        158, 23, 598
                    }
                }
            }
        };
        var el = new XElement("FavoriteSettings",
            from fav in favs.bigList
            select new XElement(fav.Name,
                from item in fav.aList
                select new XElement("ID", item)));

        string xml = el.ToString();
        Console.WriteLine(xml);

        el = XElement.Parse(xml);
        favs = new FavouriteSettings
        {
            bigList = new List<FavouriteList>(
                from outer in el.Elements()
                select new FavouriteList
                {
                    Name = outer.Name.LocalName,
                    aList = new List<int>(
                        from id in outer.Elements("ID")
                        select (int)id
                    )
                })
        };
    }
}
2 голосов
/ 01 октября 2009

Вы можете использовать следующие классы вместе с XmlSerializer для сериализации / десериализации в / из желаемого XML:

  public class FavouriteSettings
  {
    public ID[] Customer
    {
      get;
      set;
    }

    public ID[] Supplier
    {
      get;
      set;
    }
  }

  public class ID
  {
    [XmlText()]
    public int Value
    {
      get;
      set;
    }
  }
1 голос
/ 02 октября 2009

Если вы должны оставить все существующие имена в определении класса как есть, и введение иерархии классов для Клиента и Поставщика не подлежит сомнению, тогда вам понадобится взлом, подобный этому:

public class FavouriteList
{
   [XmlIgnore]
   public string Name; // this name will be "Customer" and "Supplier"

   [XmlElement("ID")]
   public List<int> aList; // to store those "ID" value
}

public class FavouriteSettings
{
   [XmlIgnore]
   public List<FavouriteList> bigList;

   [XmlElement("Customer")]
   public FavouriteList[] Customers
   {
       get { return bigList.Where(fl => fl.Name == "Customer").ToArray(); }
       set { bigList.AddRange(value); }
   }

   [XmlElement("Supplier")]
   public FavouriteList[] Suppliers
   {
       get { return bigList.Where(fl => fl.Name == "Supplier").ToArray(); }
       set { bigList.AddRange(value); }
   }
}
0 голосов
/ 01 октября 2009

Я полагаю, что вы можете использовать атрибуты, чтобы контролировать способ сериализации данных. См. Эту статью MSDN: « Атрибуты, управляющие сериализацией XML ».

0 голосов
/ 01 октября 2009

XMLSerializer (обычный) любит заниматься своим делом, и результат часто довольно уродлив. Вы можете частично контролировать сериализацию, внедрив IXmlSerializable, однако, если у вас есть что-то вроде «List», .NET его убьет.

Я думаю, что вы могли бы получить именно такой результат, используя вместо этого DataContractXmlSerializer. Пометьте класс с помощью [DataContract] и поместите [DataMember] поверх каждого элемента, который вы хотите сериализовать.

...