Сериализация объекта в XML - PullRequest
250 голосов
/ 08 ноября 2010

У меня есть класс C #, который я унаследовал.Я успешно "построил" объект.Но мне нужно сериализовать объект в XML.Есть ли простой способ сделать это?

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

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.domain.com/test")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.domain.com/test", IsNullable = false)]
public partial class MyObject
{
  ...
}

Вот то, что я думал, что мог бы сделать, но оно не работает:

MyObject o = new MyObject();
// Set o properties
string xml = o.ToString();

Как мне получить представление XML этогообъект

Ответы [ 15 ]

441 голосов
/ 08 ноября 2010

Вы должны использовать XmlSerializer для сериализации XML.Ниже приведен образец фрагмента.

 XmlSerializer xsSubmit = new XmlSerializer(typeof(MyObject));
 var subReq = new MyObject();
 var xml = "";

 using(var sww = new StringWriter())
 {
     using(XmlWriter writer = XmlWriter.Create(sww))
     {
         xsSubmit.Serialize(writer, subReq);
         xml = sww.ToString(); // Your XML
     }
 }
103 голосов
/ 31 мая 2013

Я изменил мой, чтобы он возвращал строку, а не использовал переменную ref, как показано ниже.

public static string Serialize<T>(this T value)
{
    if (value == null)
    {
        return string.Empty;
    }
    try
    {
        var xmlserializer = new XmlSerializer(typeof(T));
        var stringWriter = new StringWriter();
        using (var writer = XmlWriter.Create(stringWriter))
        {
            xmlserializer.Serialize(writer, value);
            return stringWriter.ToString();
        }
    }
    catch (Exception ex)
    {
        throw new Exception("An error occurred", ex);
    }
}

Его использование будет выглядеть так:

var xmlString = obj.Serialize();
37 голосов
/ 02 февраля 2013

Следующая функция может быть скопирована в любой объект для добавления функции сохранения XML с использованием пространства имен System.Xml.

/// <summary>
/// Saves to an xml file
/// </summary>
/// <param name="FileName">File path of the new xml file</param>
public void Save(string FileName)
{
    using (var writer = new System.IO.StreamWriter(FileName))
    {
        var serializer = new XmlSerializer(this.GetType());
        serializer.Serialize(writer, this);
        writer.Flush();
    }
}

Чтобы создать объект из сохраненного файла, добавьте следующую функцию и замените [ObjectType] с типом объекта, который будет создан.

/// <summary>
/// Load an object from an xml file
/// </summary>
/// <param name="FileName">Xml file name</param>
/// <returns>The object created from the xml file</returns>
public static [ObjectType] Load(string FileName)
{
    using (var stream = System.IO.File.OpenRead(FileName))
    {
        var serializer = new XmlSerializer(typeof([ObjectType]));
        return serializer.Deserialize(stream) as [ObjectType];
    }
}
29 голосов
/ 27 ноября 2014

Класс расширения:

using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace MyProj.Extensions
{
    public static class XmlExtension
    {
        public static string Serialize<T>(this T value)
        {
            if (value == null) return string.Empty;

            var xmlSerializer = new XmlSerializer(typeof(T));

            using (var stringWriter = new StringWriter())
            {
                using (var xmlWriter = XmlWriter.Create(stringWriter,new XmlWriterSettings{Indent = true}))
                {
                    xmlSerializer.Serialize(xmlWriter, value);
                    return stringWriter.ToString();
                }    
            }
        }
    }
}

Использование:

Foo foo = new Foo{MyProperty="I have been serialized"};

string xml = foo.Serialize();

Просто укажите ссылку на пространство имен, содержащее ваш метод расширения, в файле, в котором вы хотите его использовать, и оно будет работать (в моем примере это будет: using MyProj.Extensions;)

Обратите внимание, что если вы хотите сделать метод расширения специфичным только для определенного класса (например, Foo), вы можете заменить аргумент Tв методе расширения, например.

public static string Serialize(this Foo value){...}

28 голосов
/ 27 ноября 2012

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

public static bool Serialize<T>(T value, ref string serializeXml)
{
    if (value == null)
    {
        return false;
    }
    try
    {
        XmlSerializer xmlserializer = new XmlSerializer(typeof(T));
        StringWriter stringWriter = new StringWriter();
        XmlWriter writer = XmlWriter.Create(stringWriter);

        xmlserializer.Serialize(writer, value);

        serializeXml = stringWriter.ToString();

        writer.Close();
        return true;
    }
    catch (Exception ex)
    {
        return false;
    }
}

Вы можете позвонить с клиента.

17 голосов
/ 08 ноября 2010

Чтобы сериализовать объект, выполните:

 using (StreamWriter myWriter = new StreamWriter(path, false))
 {
     XmlSerializer mySerializer = new XmlSerializer(typeof(your_object_type));
     mySerializer.Serialize(myWriter, objectToSerialize);
 }

Также помните, что для работы XmlSerializer необходим конструктор без параметров.

16 голосов
/ 15 ноября 2015

Начну с копии ответа Бена Грипки:

public void Save(string FileName)
{
    using (var writer = new System.IO.StreamWriter(FileName))
    {
        var serializer = new XmlSerializer(this.GetType());
        serializer.Serialize(writer, this);
        writer.Flush();
    }
}

Я использовал этот код ранее. Но реальность показала, что это решение немного проблематично. Обычно большинство программистов просто сериализуют настройки при сохранении и десериализуют настройки при загрузке. Это оптимистичный сценарий. После сбоя сериализации по какой-то причине файл частично записан, файл XML не завершен и является недействительным. В результате десериализация XML не работает, и ваше приложение может аварийно завершить работу при запуске. Если файл не очень большой, я предлагаю сначала сериализовать объект в MemoryStream, а затем записать поток в файл. Это особенно важно в случае сложной пользовательской сериализации. Вы никогда не сможете проверить все случаи.

public void Save(string fileName)
{
    //first serialize the object to memory stream,
    //in case of exception, the original file is not corrupted
    using (MemoryStream ms = new MemoryStream())
    {
        var writer = new System.IO.StreamWriter(ms);    
        var serializer = new XmlSerializer(this.GetType());
        serializer.Serialize(writer, this);
        writer.Flush();

        //if the serialization succeed, rewrite the file.
        File.WriteAllBytes(fileName, ms.ToArray());
    }
}

Сценарий десериализации в реальном мире должен считаться с поврежденным файлом сериализации, это случается когда-нибудь. Функция загрузки, предоставленная Беном Грипкой, в порядке.

public static [ObjectType] Load(string fileName)
{
    using (var stream = System.IO.File.OpenRead(fileName))
    {
        var serializer = new XmlSerializer(typeof([ObjectType]));
        return serializer.Deserialize(stream) as [ObjectType];        
    }    
}

И это может быть связано с некоторым сценарием восстановления. Подходит для файлов настроек или других файлов, которые могут быть удалены в случае проблем.

public static [ObjectType] LoadWithRecovery(string fileName)
{
    try
    {
        return Load(fileName);
    }
    catch(Excetion)
    {
        File.Delete(fileName); //delete corrupted settings file
        return GetFactorySettings();
    }
}
7 голосов
/ 08 ноября 2010

Это немного сложнее, чем вызов метода ToString класса, но не намного.

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

public string SerializeObject(object obj)
{
    System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
    System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
    using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) {
        serializer.Serialize(ms, obj);
        ms.Position = 0;
        xmlDoc.Load(ms);
        return xmlDoc.InnerXml;
    }
}
5 голосов
/ 17 декабря 2018

Все приведенные выше ответы верны. Это просто самая простая версия:

private string Serialize(Object o)
{
    using (var writer = new StringWriter())
    {
        new XmlSerializer(o.GetType()).Serialize(writer, o);
        return writer.ToString();
    }
}
3 голосов
/ 08 ноября 2010

Вот хороший учебник о том, как это сделать

Вы должны в основном использовать System.Xml.Serialization.XmlSerializer класс, чтобы сделать это.

...