C#的XmlSerializer如何序列化对象为XML?

星降
发布: 2025-08-22 09:51:01
原创
670人浏览过

c#中序列化对象为xml最直接方式是使用xmlserializer类;2. 核心步骤为创建xmlserializer实例、调用serialize方法写入流;3. 处理复杂类型需注意嵌套对象自动递归、集合默认带包装元素,可用[xmlarray]或[xmlelement]定制;4. 自定义xml结构可用[xmlelement]改元素名、[xmlattribute]变属性、[xmlignore]忽略成员、[xmlinclude]支持多态;5. 常见问题包括必须提供公共无参构造函数、只读属性反序列化失败、循环引用导致栈溢出、首次序列化性能低、命名空间需手动控制;6. 对比其他序列化方式:xmlserializer适合严格xml schema场景,datacontractserializer适合.net内部数据契约,json序列化库适合现代web api和跨平台交互。

C#的XmlSerializer如何序列化对象为XML?

C#中,要将一个对象序列化成XML,最直接且常用的方式就是利用

System.Xml.Serialization
登录后复制
命名空间下的
XmlSerializer
登录后复制
类。它能将对象的公共属性和字段转换为XML元素和属性,反之亦然,实现对象与XML文档之间的双向转换。

解决方案

使用

XmlSerializer
登录后复制
将C#对象序列化为XML,核心步骤是创建一个
XmlSerializer
登录后复制
实例,指定要序列化的对象类型,然后调用其
Serialize
登录后复制
方法,将对象写入到一个流(如
FileStream
登录后复制
MemoryStream
登录后复制
)或
TextWriter
登录后复制
中。

以下是一个简单的示例,展示如何将一个

Book
登录后复制
对象序列化为XML字符串:

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

public class Book
{
    public string Title { get; set; }
    public string Author { get; set; }
    public int PublicationYear { get; set; }
    // 默认构造函数是XmlSerializer序列化和反序列化所必需的
    public Book() { }

    public Book(string title, string author, int year)
    {
        Title = title;
        Author = author;
        PublicationYear = year;
    }
}

public class XmlSerializationExample
{
    public static void Main(string[] args)
    {
        // 创建一个要序列化的对象实例
        Book myBook = new Book("The Hitchhiker's Guide to the Galaxy", "Douglas Adams", 1979);

        // 创建XmlSerializer实例,指定要序列化的类型
        XmlSerializer serializer = new XmlSerializer(typeof(Book));

        // 使用StringWriter来捕获XML输出到字符串
        using (StringWriter writer = new StringWriter())
        {
            // 执行序列化
            serializer.Serialize(writer, myBook);

            // 获取序列化后的XML字符串
            string xmlString = writer.ToString();
            Console.WriteLine("Serialized XML:");
            Console.WriteLine(xmlString);
        }

        // 也可以序列化到文件
        string filePath = "myBook.xml";
        using (FileStream fs = new FileStream(filePath, FileMode.Create))
        {
            serializer.Serialize(fs, myBook);
            Console.WriteLine($"\nObject serialized to {filePath}");
        }

        // 反序列化示例 (从文件读取)
        Console.WriteLine("\nDeserializing from file...");
        using (FileStream fsRead = new FileStream(filePath, FileMode.Open))
        {
            Book deserializedBook = (Book)serializer.Deserialize(fsRead);
            Console.WriteLine($"Deserialized Book: {deserializedBook.Title} by {deserializedBook.Author} ({deserializedBook.PublicationYear})");
        }
    }
}
登录后复制

运行这段代码,你会看到

Book
登录后复制
对象被转换成了一个结构清晰的XML,其中
Title
登录后复制
Author
登录后复制
PublicationYear
登录后复制
都成了XML元素。这感觉就像是把一个C#对象“拍扁”成了文本格式,方便存储和传输。

XmlSerializer在处理复杂类型或集合时有哪些注意事项?

当你的数据模型变得复杂,比如包含嵌套对象、列表或数组时,

XmlSerializer
登录后复制
的处理方式就显得尤为重要,而且它也提供了一些特性(Attributes)来精细控制XML的输出结构。

首先,对于嵌套对象

XmlSerializer
登录后复制
默认会递归地序列化它们。比如,如果你的
Book
登录后复制
类里有一个
Publisher
登录后复制
对象,那么
Publisher
登录后复制
的公共属性也会被序列化为XML元素,嵌套在
<Book>
登录后复制
元素内部。这很符合直觉,但如果嵌套层级很深,生成的XML可能会变得很冗长。

处理集合类型(如

List<T>
登录后复制
T[]
登录后复制
IEnumerable<T>
登录后复制
)时,
XmlSerializer
登录后复制
会默认生成一个包装元素,其名称通常是“ArrayOf”加上集合元素的类型名。比如
List<Book>
登录后复制
会序列化成
<ArrayOfBook><Book>...</Book><Book>...</Book></ArrayOfBook>
登录后复制
。如果你觉得这个默认的包装元素名不够语义化,或者根本不想要这个包装,可以使用
[XmlArray("Books")]
登录后复制
[XmlElement("Book")]
登录后复制
来定制。我个人觉得,直接使用
[XmlElement("Book")]
登录后复制
List<Book>
登录后复制
属性上,可以避免
ArrayOf
登录后复制
前缀,让XML看起来更简洁,更符合某些API的要求。

更进一步的自定义XML结构,这才是

XmlSerializer
登录后复制
的真正魅力所在:

  • [XmlElement("NewElementName")]
    登录后复制
    : 改变属性对应的XML元素名。比如,
    [XmlElement("BookTitle")] public string Title { get; set; }
    登录后复制
    会让
    Title
    登录后复制
    属性序列化为
    <BookTitle>
    登录后复制
    而不是
    <Title>
    登录后复制
  • [XmlAttribute("Year")]
    登录后复制
    : 将属性序列化为XML元素的属性而非子元素。
    [XmlAttribute("Year")] public int PublicationYear { get; set; }
    登录后复制
    会让
    PublicationYear
    登录后复制
    变成
    <Book Year="1979">
    登录后复制
    。这在XML中非常常见,比如用于ID或版本号。
  • [XmlIgnore]
    登录后复制
    : 忽略某个公共属性或字段,不将其序列化到XML中。如果你的类里有一些内部状态或只读属性,不希望暴露在XML里,这个特性就很有用。
  • [XmlArray("Items")]
    登录后复制
    [XmlArrayItem("Item")]
    登录后复制
    : 精确控制集合的包装元素和内部元素的名称。例如,
    [XmlArray("Chapters"), XmlArrayItem("Chapter")] public List<string> Chapters { get; set; }
    登录后复制
    会生成
    <Chapters><Chapter>...</Chapter></Chapters>
    登录后复制
  • [XmlInclude(typeof(DerivedType))]
    登录后复制
    : 这是处理多态性的关键。如果你的类包含一个基类类型的属性,但运行时它实际上是派生类的实例,
    XmlSerializer
    登录后复制
    默认可能无法正确序列化派生类的特有成员。通过在基类或包含属性的类上添加
    [XmlInclude(typeof(DerivedType))]
    登录后复制
    ,你可以告诉
    XmlSerializer
    登录后复制
    在序列化时,这个属性可能包含
    DerivedType
    登录后复制
    的实例,从而正确处理其成员。这对于构建灵活的数据模型非常重要。

这些特性提供了非常强大的控制力,让你能够将C#对象映射到几乎任何复杂的XML Schema。我通常会根据预期的XML输出结构,灵活运用这些特性,而不是完全依赖

XmlSerializer
登录后复制
的默认行为。

使用XmlSerializer时常见的序列化问题及如何解决?

虽然

XmlSerializer
登录后复制
功能强大,但在实际使用中,确实会遇到一些让人头疼的问题。我个人就没少在这上面踩过坑。

一个最常见、也最让人困惑的问题是:被序列化的类必须有一个公共的无参构造函数。哪怕你的类有其他带参数的构造函数,

XmlSerializer
登录后复制
在反序列化时,仍然会尝试调用这个默认的无参构造函数来创建对象实例。如果缺少,它就会抛出异常,通常是
InvalidOperationException
登录后复制
。解决方案很简单,就是给你的类加一个
public YourClass() { }
登录后复制
。这听起来有点反直觉,毕竟很多时候我们习惯用带参数的构造函数来初始化对象,但在序列化/反序列化场景下,这是个铁律。

其次,只读属性和私有字段默认是不会被

XmlSerializer
登录后复制
序列化的。
XmlSerializer
登录后复制
只关心公共的、可读写的属性和公共字段。如果你想序列化私有数据,你需要通过公共属性来暴露它,或者考虑使用
DataContractSerializer
登录后复制
,它对私有成员有更好的支持。对于只读属性(只有
get
登录后复制
没有
set
登录后复制
),
XmlSerializer
登录后复制
可以序列化它,但反序列化时无法设置其值,这可能导致数据丢失

序列猴子开放平台
序列猴子开放平台

具有长序列、多模态、单模型、大数据等特点的超大规模语言模型

序列猴子开放平台 0
查看详情 序列猴子开放平台

循环引用是另一个大问题。如果你的对象图存在循环引用(例如,

Person
登录后复制
有一个
Car
登录后复制
属性,而
Car
登录后复制
又有一个
Owner
登录后复制
属性指向同一个
Person
登录后复制
),
XmlSerializer
登录后复制
无法处理这种情况,它会陷入无限循环,最终导致
StackOverflowException
登录后复制
。这是
XmlSerializer
登录后复制
的一个设计限制。在设计数据模型时,要特别注意避免这种显式的循环引用,或者在序列化前手动断开这些引用,或者使用
[XmlIgnore]
登录后复制
来忽略那些可能导致循环的属性。

性能问题也是一个需要考虑的点。

XmlSerializer
登录后复制
在首次对特定类型进行序列化或反序列化时,会动态生成一个临时的序列化程序集。这个过程可能会比较耗时,导致第一次操作感觉有点慢。对于生产环境或需要高性能的场景,你可以使用
Sgen.exe
登录后复制
工具来预先生成这个序列化程序集,避免运行时的开销。

最后,命名空间问题有时也会让人困扰。默认情况下,

XmlSerializer
登录后复制
会生成一些默认的XML命名空间。如果你需要精确控制XML元素的命名空间,可以使用
XmlSerializerNamespaces
登录后复制
类来定义和传递命名空间前缀,或者在类和属性上使用
[XmlRoot]
登录后复制
[XmlElement]
登录后复制
[XmlAttribute]
登录后复制
等特性来指定
Namespace
登录后复制
属性。这在与外部系统集成,需要遵循严格XML Schema时尤为重要。

处理这些问题,关键在于理解

XmlSerializer
登录后复制
的工作原理和限制。很多时候,解决方案就是遵守它的“规矩”,或者在数据模型设计阶段就规避掉这些潜在的问题。

XmlSerializer与DataContractSerializer、Json.NET等其他序列化方式的对比与选择?

在.NET生态系统中,除了

XmlSerializer
登录后复制
,我们还有
DataContractSerializer
登录后复制
和用于JSON序列化的
Newtonsoft.Json
登录后复制
(或
System.Text.Json
登录后复制
)。它们各有侧重,选择哪一个取决于你的具体需求和应用场景。

XmlSerializer
登录后复制

  • 优点:对XML结构有极致的控制力,可以通过各种特性(
    [XmlElement]
    登录后复制
    ,
    [XmlAttribute]
    登录后复制
    ,
    [XmlArray]
    登录后复制
    ,
    [XmlArrayItem]
    登录后复制
    等)精确映射C#对象到复杂的XML Schema。它与SOAP Web Services(ASMX)紧密集成,是处理传统XML格式的首选。
  • 缺点:要求被序列化的类有公共无参构造函数;不擅长处理循环引用;默认只序列化公共属性和字段;首次使用性能开销较大。我个人觉得它在处理复杂XML结构时虽然强大,但也意味着配置起来可能比较繁琐。
  • 适用场景:与遗留系统交互,特别是基于SOAP的Web服务;需要严格遵循特定XML Schema的场景;对XML输出格式有精细控制需求时。

DataContractSerializer
登录后复制

  • 优点:更加面向数据契约,通过
    [DataContract]
    登录后复制
    [DataMember]
    登录后复制
    特性明确指定要序列化的成员,可以序列化私有成员;对版本控制有更好的支持(
    Order
    登录后复制
    属性);性能通常比
    XmlSerializer
    登录后复制
    好;不要求公共无参构造函数;能更好地处理循环引用(通过对象引用)。它更像是.NET内部对象序列化的通用解决方案。
  • 缺点:对生成的XML结构控制力不如
    XmlSerializer
    登录后复制
    ,生成的XML通常比较冗余,带有默认的命名空间前缀;不适合需要精确匹配外部XML Schema的场景。
  • 适用场景:WCF服务;内部应用程序之间的数据交换;当XML结构不是首要考虑,而更关注数据本身的传输和版本兼容性时。

Newtonsoft.Json
登录后复制
(Json.NET) /
System.Text.Json
登录后复制

  • 优点:这些是用于JSON序列化的库,与XML无关。JSON作为一种轻量级的数据交换格式,在现代Web应用、RESTful API和移动开发中占据主导地位。JSON序列化器通常性能优异,生成的数据体积小,易于跨平台解析。
    Newtonsoft.Json
    登录后复制
    功能强大、灵活,而
    System.Text.Json
    登录后复制
    是.NET Core/.NET 5+内置的高性能选项。
  • 缺点:无法生成XML。
  • 适用场景:构建RESTful API;前后端分离的Web应用;移动应用数据传输;任何需要轻量级、高性能、跨平台数据交换的场景。

如何选择?

我通常会这么考虑:

  • 如果你的需求是与旧的SOAP服务交互,或者必须生成/解析特定、复杂的XML文件(比如遵循某个行业标准XML Schema),那么
    XmlSerializer
    登录后复制
    几乎是唯一的选择,尽管它可能需要你投入更多精力去配置和调试。
  • 如果是在.NET应用程序内部,或者WCF服务之间进行数据传输,并且对XML的具体结构没有那么严格的要求,更注重数据契约和性能,那么
    DataContractSerializer
    登录后复制
    会是更优的选择,它更“现代”一些,用起来也更省心。
  • 如果你的项目是面向Web API、前后端分离,或者需要与非.NET平台进行数据交互,并且数据格式是JSON,那么毫无疑问,选择
    Newtonsoft.Json
    登录后复制
    System.Text.Json
    登录后复制
    。它们是现代应用数据交换的主流。

简单来说,

XmlSerializer
登录后复制
是XML结构控制的专家,
DataContractSerializer
登录后复制
是.NET内部数据契约的专家,而JSON序列化库则是Web和跨平台数据交换的专家。根据你的“输出”格式要求和“通信”对象,选择最合适的工具,这才是最高效的做法。

以上就是C#的XmlSerializer如何序列化对象为XML?的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号