Класс сериализации, атрибут "переместить" в другой элемент - PullRequest
1 голос
/ 23 января 2012

Я пытаюсь определить, где свойство класса отображается при сериализации класса: мне нужно, чтобы свойство отображалось как атрибут определенного элемента:

namespace ConsoleApplication6
{
    public class Program
    {
        static void Main(string[] args)
        {
            var myClass = new MyClass();
            myClass.MyList.Add(new Item() { ID = 1 });
            myClass.MyList.Add(new Item() { ID = 2 });
            myClass.Xxx = "Hello World!";

            var sx = new XmlSerializer(myClass.GetType());
            sx.Serialize(Console.Out, myClass);
        }

        public class MyClass
        {
            public MyClass()
            {
                MyList = new List<Item>();
            }

            public List<Item> MyList { get; set; }

            [XmlAttributeAttribute(AttributeName = "x")]
            public string Xxx { get; set; }
        }

        public class Item
        {
            public int ID { get; set; }
        }
    }
}

Это очень хорошо сериализуется в этом:

<?xml version="1.0" encoding="ibm850"?>
<MyClass xmlns:xsi=" ... " xmlns:xsd=" ... " x="Hello World!">
  <MyList>
    <Item>
      <ID>1</ID>
    </Item>
    <Item>
      <ID>2</ID>
    </Item>
  </MyList>
</MyClass>

НО: Моя проблема в том, что мне нужно, чтобы свойство Xxx отображалось как атрибут элемента <MyList>, а не корневого элемента <MyClass>, например:

...
<MyList x="Hello World!">
...

Угадаю, это должно быть возможно с использованием атрибутов XmlSerialization класса / свойств, но я не могу понять это.Я даже пытался создать подкласс List, добавив к нему свойство Xxx, но сериализация .NET XML игнорирует дополнительные свойства, и вывод XML аналогичен тому, как List <..> обычно сериализуется.

Обновление: Вот код, в котором я пытаюсь создать «пользовательский список», который наследуется от List<Item> и добавляет дополнительное свойство:

public class Program
{
    static void Main(string[] args)
    {
        var myClass = new MyClass();
        myClass.MyList.Add(new Item() { ID = 1 });
        myClass.MyList.Add(new Item() { ID = 2 });
        myClass.MyList.Xxx = "Hello World!";

        var sx = new XmlSerializer(myClass.GetType());
        sx.Serialize(Console.Out, myClass);
    }

    public class MyClass
    {
        public MyClass()
        {
            MyList = new CustomList();
        }

        public CustomList MyList { get; set; }
    }

    public class Item
    {
        public int ID { get; set; }
    }

    public class CustomList : List<Item>
    {
        [XmlAttributeAttribute(AttributeName = "x")]
        public string Xxx { get; set; }
    }
}

Выходной xml выглядит следующим образом:

<?xml version="1.0" encoding="ibm850"?>
<MyClass xmlns:xsi=" ... " xmlns:xsd=" ... ">
  <MyList>
    <Item>
      <ID>1</ID>
    </Item>
    <Item>
      <ID>2</ID>
    </Item>
  </MyList>
</MyClass>

Обратите внимание, что свойство Xxx не представлено в xml ...

Ответы [ 3 ]

1 голос
/ 23 января 2012

Я думаю, что для такого уровня контроля вам нужно будет использовать интерфейс IXmlSerializable. Я не думаю, что использование атрибутов будет работать здесь.

0 голосов
/ 23 января 2012

Этот пост содержит дополнительную информацию, в том числе несколько вариантов: Когда класс наследуется от List <>, XmlSerializer не сериализует другие атрибуты

Резюме:

  • IXmlSerializable (как упомянуто Каем)
  • DataContractSerializer
  • Создайте новый класс, где X (ваш атрибут) является свойством, и предоставьте дополнительное свойство, которое является списком (поэтому вместо списка подклассов просто создайте класс-оболочку). Например:

    public class MyListWrapper<T> 
    {
       public MyListWrapper()
       {
          Data = new List<T>();
       }
    
       [XmlAttribute(AttributeName="x")]
       public string Xxx { get; set; }
    
       [XmlElement]
       public List<T> Data { get; set; }
    }
    

    Обратите внимание, что при этом Предметы будут выводиться как элементы «Данные». Если вы хотите удалить параметр универсального типа в Data и сделать его List (Item), вы можете получить элементы.

Надеюсь, это поможет!

0 голосов
/ 23 января 2012

Согласно этому обсуждению MSDN :

XmlSerializer не сериализует ни одного члена, если это коллекция.Только элементы коллекции получают сериализацию.Это сделано специально, в основном было принято решение обрабатывать коллекции как массивы, а не как классы с несколькими свойствами, поэтому коллекции должны выглядеть как массивы на проводе, поэтому они не имеют никаких элементов, кроме элементов коллекции, и могут быть «сведены»добавив [XmlElement] к члену типа ICollection.

Таким образом, очевидно, что описанный вами недостаток задуман.Если вы не решите запустить полученный XML через некоторые преобразования, я не уверен, как вы планируете заставить это работать, используя атрибуты сериализации XML.

...