Serialize an object to XML

2018-12-31 09:25发布

I have a C# class that I have inherited. I have successfully "built" the object. But I need to serialize the object to XML. Is there an easy way to do it?

It looks like the class has been set up for serialization, but I'm not sure how to get the XML representation. My class definition looks like this:

[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
{
  ...
}

Here is what I thought I could do, but it doesn't work:

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

How do I get the XML representation of this object?

14条回答
呛了眼睛熬了心
2楼-- · 2018-12-31 10:14

All upvoted answers above are correct. This is just simplest version:

private string Serialize(Object o)
{
    using (var writer = new StringWriter())
    {
        new XmlSerializer(o.GetType()).Serialize(writer, o);
        return writer.ToString();
    }
}
查看更多
春风洒进眼中
3楼-- · 2018-12-31 10:18

I will start with the copy answer of Ben Gripka:

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();
    }
}

I used this code earlier. But reality showed that this solution is a bit problematic. Usually most of programmers just serialize setting on save and deserialize settings on load. This is an optimistic scenario. Once the serialization failed, because of some reason, the file is partly written, XML file is not complete and it is invalid. In consequence XML deserialization does not work and your application may crash on start. If the file is not huge, I suggest first serialize object to MemoryStream then write the stream to the File. This case is especially important if there is some complicated custom serialization. You can never test all cases.

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());
    }
}

The deserialization in real world scenario should count with corrupted serialization file, it happens sometime. Load function provided by Ben Gripka is fine.

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];        
    }    
}

And it could be wrapped by some recovery scenario. It is suitable for settings files or other files which can be deleted in case of problems.

public static [ObjectType] LoadWithRecovery(string fileName)
{
    try
    {
        return Load(fileName);
    }
    catch(Excetion)
    {
        File.Delete(fileName); //delete corrupted settings file
        return GetFactorySettings();
    }
}
查看更多
裙下三千臣
4楼-- · 2018-12-31 10:21

The following function can be copied to any object to add an XML save function using the System.Xml namespace.

/// <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();
    }
}

To create the object from the saved file, add the following function and replace [ObjectType] with the object type to be created.

/// <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];
    }
}
查看更多
忆尘夕之涩
5楼-- · 2018-12-31 10:21

Here is a good tutorial on how to do this

You should basically use System.Xml.Serialization.XmlSerializer class to do this.

查看更多
琉璃瓶的回忆
6楼-- · 2018-12-31 10:26

I modified mine to return a string rather than use a ref variable like below.

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);
    }
}

Its usage would be like this:

var xmlString = obj.Serialize();
查看更多
只若初见
7楼-- · 2018-12-31 10:27

Or you can add this method to your object:

    public void Save(string filename)
    {
        var ser = new XmlSerializer(this.GetType());
        using (var stream = new FileStream(filename, FileMode.Create))
            ser.Serialize(stream, this);
    }
查看更多
登录 后发表回答