LinkedList <T>нельзя сериализовать с помощью XMLSerializer - PullRequest
0 голосов
/ 10 февраля 2010

LinkedList нельзя сериализовать с использованием XmlSerializer.

Теперь, как сохранить / получить данные из сериализованного объекта LinkedList. Должен ли я реализовать пользовательскую сериализацию?

Что я пытался сделать:

using System.Xml.Serialization;

[Serializable()]
public class TestClass
{
    private int _Id;
    private string _Name;
    private int _Age;
    private LinkedList<int> _linkedList = new LinkedList<int>();

    public string Name {
        get { return _Name; }
        set { _Name = value; }
    }
    
    public string Age {
        get { return _Age; }
        set { _Age = value; }
    }
    
    [XmlArray()]
    public List<int> MyLinkedList {
        get { return new List<int>(_linkedList); }
        set { _linkedList = new LinkedList<int>(value); }
    }
}

Что я получил (имя, возраст и некоторые элементы в mylinkedlist):

<?xml version="1.0"?>
<TestClass 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>testName</Name>
  <Age>10</Age>
  <MyLinkedList />
</TestClass>

Итак, элементы в связанном списке не были сериализованы ...: (

1 Ответ

4 голосов
/ 10 февраля 2010

Одной из возможностей может быть создание сериализуемой коллекции, которая содержит те же объекты, что и связанный список. Например. (Непроверенные):

LinkedList<Foo> ll = PopulateLinkedList();
List<Foo> list = new List<Foo>(ll);

Затем вместо этого сериализуйте list. Это не приведет к большим накладным расходам, если Foo является ссылочным типом, и вас не волнует тот факт, что вставки / удаления теперь более дороги, потому что вы используете только List<T> для хранить ссылки на данные для сериализации и десериализации. Когда вы извлекаете его из сериализованного потока, вы можете просто превратить его в LinkedList<T>, чтобы получить все те преимущества, для которых вы в первую очередь использовали связанный список.


Вот небольшое консольное приложение, которое я только что продемонстрировал. Я сделал это в VS2008, но я не думаю, что использовал что-то удивительное - только синтаксис инициализации массива, чтобы сэкономить вертикальное пространство.

Пример кода:

[Serializable]
public class MyClass
{
    private string name;
    private int age;
    private LinkedList<int> linkedList = new LinkedList<int>();

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public int Age
    {
        get { return age; }
        set { age = value; }
    }

    [XmlArray]
    public List<int> MyLinkedList
    {
        get { return new List<int>(linkedList); }
        set { linkedList = new LinkedList<int>(value); }
    }
}

И основной код приложения:

class Program
{
    static void Main(string[] args)
    {
        MyClass c = new MyClass();

        c.Age = 42;
        c.Name = "MyName";
        c.MyLinkedList = new List<int>() { 1, 4, 9 }; // Your property impl requires this be set all at once, not one element at a time via the property.

        XmlSerializer s = new XmlSerializer(typeof(MyClass));
        StringWriter outStream = new StringWriter();
        s.Serialize(outStream, c);

        Console.Write(outStream.ToString());

        return;
    }
}

Это выводит на консоль следующее:

<?xml version="1.0" encoding="utf-16"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>MyName</Name>
  <Age>42</Age>
  <MyLinkedList>
    <int>1</int>
    <int>4</int>
    <int>9</int>
  </MyLinkedList>
</MyClass>
...