C#学习之XML中序列化对象

本文介绍如何使用.NET框架中的XmlSerializer类实现对象的序列化与反序列化。包括序列化过程中的注意事项及示例代码,展示了如何将对象转换为XML格式并恢复。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

序列化是把一个对象持久化到磁盘中的过程。应用程序的另一部分,甚至另一个引用程序都可以反序列化对象,使它的状态与序列化之前相同。

序列化使用的是System.Xml.Serialization名称空间中最重要的XmlSerializer类,要序列化对象,首先需要实例化一个XmlSerializer对象,指定要序列化的对象类型,然后实例化一个流/写入器对象,一把文件写入流/文档中。最后一步实在Xmlserializer上调用Serializer()方法,给它传递流/写入器对象和要序列化的对象。

被序列化的数据可以为基元类型的数据、字段、数组,以及XmlElement和XmlAttribute对象格式的内嵌XML。

为了从XML文档中反序列化对象,应执行上述过程的逆过程。即创建一个流/读取器对象和一个XmlSerializer对象,然后给DeSerializer()方法传递该流/读取器对象。这个方法返回反序列化的对象,尽管它需要强制转换为正确的类型。

注意:XML序列化程序不能转换私有数据,只能转换公有数据,它也不能序列化对象图表。但是,这并不是一个严格的限制。对类进行仔细的涉及,就很容易避免这个问题,如果需要序列化公共数据和私有数据,以及包含许多潜逃对象的对象图形,就可以使用System.Runtime.SerializationFormatters.Binary名称空间。

现在就写一些示例代码看一下XML如何序列化和反序列化。

首先需要创建一个类,里面包含一些私有数据和一些公共数据。

Product.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace GenerateXML
{
    [System.Xml.Serialization.XmlRootAttribute()]
    public class Product
    {
        private int prodId;
        private string prodName;
        private int suppId;
        private int catId;
        private string qtyPerUnit;
        private Decimal unitPrice;
        private short unitsInStock;
        private short unitsOnOrder;
        private short reorderLvl;
        private bool discont;
        private int disc;

        //added the Discount attribute
        [XmlAttributeAttribute(AttributeName = "Discount")]
        public int Discount
        {
            get { return disc; }
            set { disc = value; }
        }
        [XmlElementAttribute()]
        public int ProductID
        {
            get { return prodId; }
            set { prodId = value; }
        }
        [XmlElementAttribute()]
        public string ProductName
        {
            get { return prodName; }
            set { prodName = value; }
        }
        [XmlElementAttribute()]
        public int SupplierID
        {
            get { return suppId; }
            set { suppId = value; }
        }
        [XmlElementAttribute()]
        public int CategoryID
        {
            get { return catId; }
            set { catId = value; }
        }
        [XmlElementAttribute()]
        public string QuantityPerUnit
        {
            get { return qtyPerUnit; }
            set { qtyPerUnit = value; }
        }
        [XmlElementAttribute()]
        public Decimal UnitPrice
        {
            get { return unitPrice; }
            set { unitPrice = value; }
        }
        [XmlElementAttribute()]
        public short UnitsInStock
        {
            get { return unitsInStock; }
            set { unitsInStock = value; }
        }
        [XmlElementAttribute()]
        public short UnitsOnOrder
        {
            get { return unitsOnOrder; }
            set { unitsOnOrder = value; }
        }
        [XmlElementAttribute()]
        public short ReorderLevel
        {
            get { return reorderLvl; }
            set { reorderLvl = value; }
        }
        [XmlElementAttribute()]
        public bool Discontinued
        {
            get { return discont; }
            set { discont = value; }
        }

        public override string ToString()
        {
            StringBuilder outText = new StringBuilder();
            outText.Append(prodId);
            outText.Append(" ");
            outText.Append(prodName);
            outText.Append(" ");
            outText.Append(unitPrice);
            return outText.ToString();
        }
    }
}

在Product类定义上面的特性中调用的XmlRootAttribute()方法把这个类表示为根元素。包含XmlElementAttribute()方法的特性标识该特性下面的成员表示一个XML元素。在刚开始序列化应用的时候,要注意Class前面的public字段一定要加上,否则会出现“因其保护级别而不可访问。只能处理公共类型。”的错误。

其次需要的是序列化的方法

        public string Serializer(Type type, object obj)
        {
            MemoryStream Stream = new MemoryStream();
            XmlSerializer xml = new XmlSerializer(type);
            try
            {
                //序列化对象
                xml.Serialize(Stream, obj);
            }
            catch (InvalidOperationException)
            {
                throw;
            }
            Stream.Position = 0;
            StreamReader sr = new StreamReader(Stream);
            string str = sr.ReadToEnd();
         
            sr.Dispose();
            Stream.Dispose();
 
            return str;
        }

这里主要是以流的方式进行序列化。其中tyoe就是product实例化后用GetType()方法获得的type,object则是实例化的product。这样就可以返回序列化后的字符串样式。

<?xml version="1.0"?>
<Product xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Discount="0">
  <ProductID>200</ProductID>
  <ProductName>Serialize Objects</ProductName>
  <SupplierID>1</SupplierID>
  <CategoryID>100</CategoryID>
  <QuantityPerUnit>6</QuantityPerUnit>
  <UnitPrice>1000</UnitPrice>
  <UnitsInStock>10</UnitsInStock>
  <UnitsOnOrder>0</UnitsOnOrder>
  <ReorderLevel>1</ReorderLevel>
  <Discontinued>false</Discontinued>
</Product>

我们在这里可以看到Discount作为XmlAttributeAttribute()时,它是根节点的一个属性。而其余的都是XML元素。

对于反序列化,则相对比较简单,其方法大致如下:

 public object Deserialize(Type type, Stream stream)
        {
            XmlSerializer xmldes = new XmlSerializer(type);
            return xmldes.Deserialize(stream);
        }

这里的stream就是这个Product类对应的Xml,type就是product类实例化后用GetType()方法获得的type,这样就可以得到一个反序列化后的object,最后通过强制转换可以还原成一个Product。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值