C#操作Xml:XmlSerializer 对象的Xml序列化和反序列化

摘要:
˃<int>10</int>“){//声明序列化对象实例serializerXmlSerializer=newXmlSerializer;//反序列化并将反序列化结果值分配给变量iinti=serializer.Deserialize;//输出反序列化结果Console.WriteLine;Console.Read();}}上面的代码以最简单的方式说明了xml序列化和反序列化的过程。Net系统类库为我们做了大量工作,序列化和反化非常简单。自定义对象的Xml序列化:System。XmlSerialization命名空间中有一系列属性类,用于控制复杂类型的序列化。对象数组的Xml序列化:需要XmlArrayAttribute和XmlArrayItemAttribute才能对数组进行Xml序列化;XmlArrayAttribute指定数组元素的Xml节点名称,XmlArrayItemAttribute指定数组元素中的Xml名称。
这篇随笔对应的.Net命名空间是System.Xml.Serialization;文中的示例代码需要引用这个命名空间。
为什么要做序列化和反序列化?
.Net程序执行时,对象都驻留在内存中;内存中的对象如果需要传递给其他系统使用;或者在关机时需要保存下来以便下次再次启动程序使用就需要序列化和反序列化。
范围:本文只介绍xml序列化,其实序列化可以是二进制的序列化,也可以是其他格式的序列化。
看一段最简单的Xml序列化代码
1
2
3
4
5
6
7
8
9
10
11
12
classProgram
{
    staticvoidMain(string[] args)
    {
        inti = 10;
        //声明Xml序列化对象实例serializer
        XmlSerializer serializer = newXmlSerializer(typeof(int));
        //执行序列化并将序列化结果输出到控制台
        serializer.Serialize(Console.Out, i);
        Console.Read();
    }
}

上面代码对int i进行了序列化,并将序列化的结果输出到了控制台,输出结果如下

<?xmlversion="1.0" encoding="gb2312"?>
<int>10</int>

可以将上述序列化的xml进行反序列化,如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
staticvoidMain(string[] args)
{
    using(StringReader rdr = newStringReader(@"<?xml version=""1.0"" encoding=""gb2312""?>
<int>10</int>"))
    {
        //声明序列化对象实例serializer
        XmlSerializer serializer = newXmlSerializer(typeof(int));
        //反序列化,并将反序列化结果值赋给变量i
        inti = (int)serializer.Deserialize(rdr);
        //输出反序列化结果
        Console.WriteLine("i = "+ i);
        Console.Read();
    }
}

以上代码用最简单的方式说明了xml序列化和反序列化的过程,.Net系统类库为我们做了大量的工作,序列化和反序列化都非常简单。但是在现实中业务需求往往比较复杂,不可能只简单的序列化一个int变量,显示中我们需要对复杂类型进行可控制的序列化。

自定义对象的Xml序列化:

System.Xml.Serialization命名空间中有一系列的特性类,用来控制复杂类型序列化的控制。例如XmlElementAttribute、XmlAttributeAttribute、XmlArrayAttribute、XmlArrayItemAttribute、XmlRootAttribute等等。

看一个小例子,有一个自定义类Cat,Cat类有三个属性分别为Color,Saying,Speed。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
namespaceUseXmlSerialization
{
    classProgram
    {
        staticvoidMain(string[] args)
        {
            //声明一个猫咪对象
            varc = newCat { Color = "White", Speed = 10, Saying = "White or black,  so long as the cat can catch mice,  it is a good cat"};
 
            //序列化这个对象
            XmlSerializer serializer = newXmlSerializer(typeof(Cat));
 
            //将对象序列化输出到控制台
            serializer.Serialize(Console.Out, c);
 
            Console.Read();
        }
    }
 
    [XmlRoot("cat")]
    publicclassCat
    {
        //定义Color属性的序列化为cat节点的属性
        [XmlAttribute("color")]
        publicstringColor { get; set; }
 
        //要求不序列化Speed属性
        [XmlIgnore]
        publicintSpeed { get; set; }
 
        //设置Saying属性序列化为Xml子元素
        [XmlElement("saying")]
        publicstringSaying { get; set; }
    }
}

可以使用XmlElement指定属性序列化为子节点(默认情况会序列化为子节点);或者使用XmlAttribute特性制定属性序列化为Xml节点的属性;还可以通过XmlIgnore特性修饰要求序列化程序不序列化修饰属性。

对象数组的Xml序列化:

数组的Xml序列化需要使用XmlArrayAttribute和XmlArrayItemAttribute;XmlArrayAttribute指定数组元素的Xml节点名,XmlArrayItemAttribute指定数组元素的Xml节点名。

如下代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*玉开技术博客 http://www.cnblogs.com/yukaizhao */
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Xml.Serialization;
 
namespaceUseXmlSerialization
{
    classProgram
    {
        staticvoidMain(string[] args)
        {
            //声明一个猫咪对象
            varcWhite = newCat { Color = "White", Speed = 10, Saying = "White or black,  so long as the cat can catch mice,  it is a good cat"};
            varcBlack = newCat { Color = "Black", Speed = 10, Saying = "White or black,  so long as the cat can catch mice,  it is a good cat"};
 
            CatCollection cc = newCatCollection { Cats = newCat[] { cWhite,cBlack} };
 
            //序列化这个对象
            XmlSerializer serializer = newXmlSerializer(typeof(CatCollection));
 
            //将对象序列化输出到控制台
            serializer.Serialize(Console.Out, cc);
 
            Console.Read();
        }
    }
 
    [XmlRoot("cats")]
    publicclassCatCollection
    {
        [XmlArray("items"),XmlArrayItem("item")]
        publicCat[] Cats { get; set; }
    }
 
    [XmlRoot("cat")]
    publicclassCat
    {
        //定义Color属性的序列化为cat节点的属性
        [XmlAttribute("color")]
        publicstringColor { get; set; }
 
        //要求不序列化Speed属性
        [XmlIgnore]
        publicintSpeed { get; set; }
 
        //设置Saying属性序列化为Xml子元素
        [XmlElement("saying")]
        publicstringSaying { get; set; }
    }
}

以上代码将输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xmlversion="1.0" encoding="gb2312"?>
w.w3.org/2001/XMLSchema">
  <items>
    <itemcolor="White">
      <saying>White or black,  so long as the cat can catch mice,  it is a good
cat</saying>
    </item>
    <itemcolor="Black">
      <saying>White or black,  so long as the cat can catch mice,  it is a good
cat</saying>
    </item>
  </items>
</cats>

XmlSerializer内存泄漏问题:

多谢chenlulouis,仔细看了下msdn,确实存在泄漏的情况,msdn说明如下:

动态生成的程序集

为了提高性能,XML 序列化基础结构将动态生成程序集,以序列化和反序列化指定类型。此基础结构将查找并重复使用这些程序集。此行为仅在使用以下构造函数时发生:

XmlSerializer(Type)
XmlSerializer.XmlSerializer(Type, String)

如果使用任何其他构造函数,则会生成同一程序集的多个版本,且绝不会被卸载,这将导致内存泄漏和性能降低。最简单的解决方案是使用先前提到的两个构造函数的其中一个。否则,必须在 Hashtable 中缓存程序集,如以下示例中所示。

也就是说我们在使用XmlSerializer序列化,初始化XmlSerializer对象时最好使用下面两个构造函数否则会引起内存泄漏。
XmlSerializer(Type)
XmlSerializer.XmlSerializer(Type, String)

C#处理Xml的相关随笔:

免责声明:文章转载自《C#操作Xml:XmlSerializer 对象的Xml序列化和反序列化》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C#调用C++dll,传指针释放内存问题MFC入门(三)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

CString转string

如题,找了半天。。。 1 //CString转string 2 3 USES_CONVERSION; 4 CString temp; 5 temp = _T("kjdsaflkjdlfkj"); 6 char* s_char = W2A(temp); 7 string ss = s_char;...

使用WMI控制Windows进程 和服务

1.使用WMI控制Windows进程 本文主要介绍两种WMI的进行操作:检查进程是否存在、创建新进行 代码如下: using System; using System.Collections.Generic; using System.Text; using System.Management; using System.Threa...

[Android Security] 静态分析Android程序——smali文件解析

cp : https://blog.csdn.net/hp910315/article/details/51823236 cp : http://www.jb51.net/softjc/119036.html 静态分析Android程序的两种方法: 一、阅读反编译生成的Dalvik字节码。 1、使用文本编辑器阅读baksmali反编译生成的smali文件...

Android占位符

<xliff:g>标签介绍:属性id可以随便命名属性值举例说明%n$ms:代表输出的是字符串,n代表是第几个参数,设置m的值可以在输出之前放置空格%n$md:代表输出的是整数,n代表是第几个参数,设置m的值可以在输出之前放置空格,也可以设为0m,在输出之前放置m个0%n$mf:代表输出的是浮点数,n代表是第几个参数,设置m的值可以控制小数位数,...

JBoss环境搭建及部署Web项目

http://blog.csdn.net/pop303/article/details/7210290 赶在年前学习了一下JBOSS,之前觉得JBOSS相关资料会有很多,不过现在发现很少,在亚马逊出也是很少,只有一个“JBoss实战:服务器配置指南 ”,不过我找到了英文版,有要的可以邮件给大家。我想从不会JBOSS开始进行,到我打包部署到JBOSS后能...

app微信支付-java服务端接口 支付-查询-退款

个人不怎么看得懂微信的文档,看了很多前辈的写法,终于调通了,在这里做一下记录。 首先来定义各种处理类(微信支付不需要特殊jar包,很多处理需要自己封装,当然也可以自己写完打个jar包) 参数要用jdom解析   自行导入jar包    或者在maven pom.xml中导入  <dependency> <groupId>org...