我继承了一个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表示形式?


当前回答

现在可能太晚了,但是只有用户定义的命名空间是序列化的:

public static string XmlSerialize<T>(this T obj) where T : class
        {
            Type serialType = typeof(T);
            var xsSubmit = new XmlSerializer(serialType);

            XmlWriterSettings xws = new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true };
            

            var Namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {           
            new XmlQualifiedName(string.Empty,  GetXmlNameSpace(serialType) ?? string.Empty )


        });
 private static string GetXmlNameSpace(Type target)
        {
            XmlRootAttribute attribute = (XmlRootAttribute)Attribute.GetCustomAttribute(target, typeof(XmlRootAttribute));
            return attribute == null ? null : attribute.Namespace;
        }

并在自定义类中定义命名空间

 [XmlRoot("IdentityTerminal",Namespace = "http://my-name-space/XMLSchema")]
   
    public class IdentityTerminal
    {
    }

这段代码允许只使用用户定义的名称空间,而忽略默认的名称空间。

其他回答

必须使用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
     }
 }

根据泛型类的@kiquenet请求:

public class MySerializer<T> where T : class
{
    public static string Serialize(T obj)
    {
        XmlSerializer xsSubmit = new XmlSerializer(typeof(T));
        using (var sww = new StringWriter())
        {
            using (XmlTextWriter writer = new XmlTextWriter(sww) { Formatting = Formatting.Indented })
            {
                xsSubmit.Serialize(writer, obj);
                return sww.ToString();
            }
        }
    }
}

用法:

string xmlMessage = MySerializer<MyClass>.Serialize(myObj);

这比调用类的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;
    }
}

现在可能太晚了,但是只有用户定义的命名空间是序列化的:

public static string XmlSerialize<T>(this T obj) where T : class
        {
            Type serialType = typeof(T);
            var xsSubmit = new XmlSerializer(serialType);

            XmlWriterSettings xws = new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true };
            

            var Namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {           
            new XmlQualifiedName(string.Empty,  GetXmlNameSpace(serialType) ?? string.Empty )


        });
 private static string GetXmlNameSpace(Type target)
        {
            XmlRootAttribute attribute = (XmlRootAttribute)Attribute.GetCustomAttribute(target, typeof(XmlRootAttribute));
            return attribute == null ? null : attribute.Namespace;
        }

并在自定义类中定义命名空间

 [XmlRoot("IdentityTerminal",Namespace = "http://my-name-space/XMLSchema")]
   
    public class IdentityTerminal
    {
    }

这段代码允许只使用用户定义的名称空间,而忽略默认的名称空间。

我将从本·格里普卡的回答开始:

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

现实场景中的反序列化应该与损坏的序列化文件算在一起,它有时会发生。负载函数由Ben Gripka提供。

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();
    }
}
public string ObjectToXML(object input)
{
    try
    {
        var stringwriter = new System.IO.StringWriter();
        var serializer = new XmlSerializer(input.GetType());
        serializer.Serialize(stringwriter, input);
        return stringwriter.ToString();
    }
    catch (Exception ex)
    {
        if (ex.InnerException != null)
            ex = ex.InnerException;

        return "Could not convert: " + ex.Message;
    }
}

//Usage
var res = ObjectToXML(obj)

您需要使用以下类:

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