.NET XML-сериализация и нулевые коллекции - PullRequest
5 голосов
/ 27 января 2010

У меня есть класс с некоторыми коллекциями в них, и я хотел бы сериализовать экземпляры этого класса в XML без необходимости инициализировать коллекции как пустые и без необходимости реализации IXmlSerializable. Мне все равно, если он создает пустые элементы, или не создает элементы вообще. Просто он работает без инициализации коллекции для каждого свойства на основе коллекции.

Я посмотрел на все атрибуты XML, которыми могу украсить свойства, и не добился успеха в этом. Это кажется простой вещью, которая может иметь элемент или вообще не иметь элемента. Затем, когда он десериализуется, он просто оставляет их нулевыми или игнорирует их.

Вот простая версия класса, используемая для решения этой проблемы. Используя это и значения по умолчанию, вы получаете исключение «Ссылка на объект не установлена ​​на экземпляр объекта» из-за того, что коллекции равны нулю;

public class MyClass
{
    public string Name { get; set; }
    public bool IsAlive { get; set; }
    public List<Car> Cars { get; set; }
    public List<Home> Homes { get; set; }
    public List<Pet> Pets { get; set; }

    public void ToXmlFile(string fileName)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
        TextWriter writer = new StreamWriter(fileName);
        serializer.Serialize(writer, this);
        writer.Close();
    }
}

EDIT Спасибо за помощь, ребята, оказывается, проблема была в моем методе GetHashCode, который не обрабатывал нуль правильно. Как только я исправил это, все было хорошо. Я отметил первый ответ, который будет правильным. Извините за красную сельдь, но работа с вами, ребята, помогла.

Ответы [ 4 ]

5 голосов
/ 27 января 2010

Вам не нужно инициализировать коллекции, чтобы сериализовать класс в XML. Вот простая программа для демонстрации:

class Program
{
    static void Main(string[] args)
    {
        MyClass c = new MyClass() { Name = "Test", IsAlive = true };
        XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
        using (MemoryStream ms = new MemoryStream())
        {
            serializer.Serialize(ms, c);
            Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
        }
        Console.ReadLine();
    }
}

Будет напечатан следующий вывод:

<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>Test</Name>
  <IsAlive>true</IsAlive>
</MyClass>

Другими словами, null свойства коллекции ведут себя так же, как и любое другое свойство null - они вообще не сериализуются (если вы не измените значение по умолчанию, которого у меня нет).

0 голосов
/ 27 января 2010

Я думаю, что установка типа возврата метода XMLSerialisation в bool позволит вам обрабатывать ошибки более безопасным способом, в отличие от текущего метода:

public bool ToXmlFile(string fileName)
{
    if(fileName != "")
    {
       XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
       TextWriter writer = new StreamWriter(fileName);
       serializer.Serialize(writer, this);
       writer.Close();
       return true;
    }
    return false;
}

Что может быть использовано следующим образом:

if(ToXMLFile)
{
     MessageBox.Show("Save Succesful");
}
else
(
     MessageBox.Show("Save unsuccesful");
)

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

0 голосов
/ 27 января 2010

Вы упоминаете исключение во время (де) сериализации; то, что у вас есть, должно работать хорошо (по крайней мере, в зависимости от того, как вы определяете вопрос). Интересно, есть ли у вас:

public class MyClass
{
    public string Name { get; set; }
    public bool IsAlive { get; set; }
    public List<Car> Cars { get; private set; }
    public List<Home> Homes { get; private set; }
    public List<Pet> Pets { get; private set; }
}

(нередко не нужен публичный сеттер)

Ну, XmlSerializer суетливо по этому поводу; вам либо нужен публичный сеттер, либо (как кто-то недавно указывал) нет сеттер; например:

public class MyClass
{
    public string Name { get; set; }
    public bool IsAlive { get; set; }
    private readonly List<Car> cars = new List<Car>();
    public List<Car> Cars { get { return cars; } }
    private readonly List<Home> homes = new List<Home>();
    public List<Home> Homes { get { return homes; } }
    private readonly List<Pet> pets = new List<Pet>();
    public List<Pet> Pets { get { return pets; } }
}
0 голосов
/ 27 января 2010

Вы можете сериализовать это без проблем, только вы должны отправить типы машины, дома и питомца при сериализации в параметре extraTypes.

...