【题外话】

先前则常用.NET中之序列化,但是常用的BinaryFormatter,也就是是二进制文件之序列化,却鲜用XML的序列化。对于XML序列化,.NET中相同提供了一个大有益之家伙XmlSerializer,其得以充分有益于的拿对象序列化为XML文件或者用XML文件相反序列化为目标。但是XML序列化与第二前进制序列化却同时过剩的分,在刚刚开头之下可能会见遇上有疑惑。

 

【文章索引】

  1. XmlSerializer的作用
  2. 从今定义XML结构的照射
  3. 不能够序列化的情节
  4. 出口格式的设置

 

【一、XmlSerializer的作用】

.NET提供了特别便宜的XML序列化工具XmlSerializer,与亚上制序列化工具BinaryFormatter不同,XmlSerializer位于System.Xml.Serialization。根据MSDN上针对XmlSerializer的辨证来拘禁,“XML
序列化是将目标的公家性质和字段改换为序列格式(这里是靠
XML)以便存储或传输的经过。反序列化则是打 XML
输出中再次创设原始状态的靶子。可以将序列化视为将目标的状态保存至流动或缓冲区的法子”,也就是说,我们得一直用XmlSerializer序列化对象吃的性质和字段。

待专注的是,只有public的特性与字段才是足以吃序列化的,如果设置的也internal或者private的性质或字段都是不克叫序列化的。当然,要序列化的靶子的接近为亟须是public的,否则会扔来下列的要命:

图片 1

除此之外,要想序列化对象吃的字段或者性质,还亟需确保字段和属性是可读而写的。例如,readonly的字段是未可以序列化的,没有get或set访问器的性质为是免得以序列化的(当然你可选当set访问器里什么啊未写,那么尽管能够序列化,但是反序列化的时候即便成空的呀)。当然,static和const的字段和性质为是勿见面为序列化的,标记为[Obsolete]的也罢非会见于序列化。此外,除了要求近似是public的外侧,还亟需该发一个无参的构造方法,否则也会见丢弃来怪。

至于XmlSerializer的下,其实非常简单,只待几行代码即可兑现以一个目标序列化:

图片 2图片 3

 1 void SaveToFile(String filePath, Object obj)
 2 {
 3     FileStream fs = null;
 4 
 5     try
 6     {
 7         fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);
 8         XmlSerializer xs = new XmlSerializer(obj.GetType());
 9 
10         xs.Serialize(fs, obj);
11     }
12     finally
13     {
14         if (fs != null)
15         {
16             fs.Close();
17         }
18     }
19 }

View Code

要么,反序列化。

图片 4图片 5

 1 T LoadFromFile<T>(String filePath)
 2 {
 3     FileStream fs = null;
 4 
 5     try
 6     {
 7         fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
 8         XmlSerializer xs = new XmlSerializer(typeof(T));
 9 
10         return (T)xs.Deserialize(fs);
11     }
12     finally
13     {
14         if (fs != null)
15         {
16             fs.Close();
17         }
18     }
19 }

View Code

 

【二、自定义XML结构的照】

假设按上述的代码进行序列化,则可将对象吃的备公共性质与字段都序列化进XML文件中。对象中的每个属性或字段都见面序列化为一个子元素,如果目标被还起另的目标要数组等还会发生更要命的子元素。但是有时我们也许除了子元素外尚用序列化节点的特性,或者需要修改映射的称等等,那么我们就待对类中的性能或者字段添加特性(Attributes)了。

及XML序列化相关的周边的性状产生:

1、[XmlAttribute]:可以拿点名字段或性质序列化为元素的属性,而不是子元素。除了直接当字段或性质上直接写“[XmlAttribute]”外,还好针对其传播参数,例如“[XmlAttribute(“identity”)]”,可以更改映射的号。例如:

[XmlAttribute("identity")]
public Int32 ID;

接近定义和序列化后底结果如下:

图片 6图片 7

public class Student
{
    [XmlAttribute("identity")]
    public Int32 ID;
    public String Name;
}

View Code

图片 8图片 9

<?xml version="1.0"?>
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" identity="1">
  <Name>姓名</Name>
</Student>

View Code

2、[XmlElement]:虽然默认就好将字段或性质序列化为子元素,但是要要是改映射的称呼,还是需要靠这个特点的。与[XmlAttribute]仿佛,其为堪无扩散或传播参数,当不传播参数时,与不加以该特性相同;当传入参数时,则可以修改映射的名号。例如:

[XmlElement("UserName")]
public String Name;

看似定义和序列化后的结果如下:

图片 10图片 11

public class Student
{
    public Int32 ID;
    [XmlElement("UserName")]
    public String Name;
}

View Code

图片 12图片 13

<?xml version="1.0"?>
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ID>1</ID>
  <UserName>姓名</UserName>
</Student>

View Code

3、[XmlText]:除了能排化为属性或者子元素外,还好直接当该因素的公文内容(InnerText),例如有只近乎Student,有一个ID我们要序列化为属性,还有一个Name我们想直接当做Student的情而未是子元素,那么我们虽好在Name上以[XmlText]了。例如:

[XmlText]
public String Name;

好像定义和序列化后底结果如下:

图片 14图片 15

public class Student
{
    [XmlAttribute]
    public Int32 ID;
    [XmlText]
    public String Name;
}

View Code

图片 16图片 17

<?xml version="1.0"?>
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="1">姓名</Student>

View Code

4、[XmlIgnore]:如果一个属性或字段我们不愿意序列化(比如该属性是由此任何字段获取到的,并没set访问器等等),那么我们得以经过[XmlIgnore]来被序列化器来忽略这个特性或字段。例如:

[XmlIgnore]
public Int32 NameLength { get { return this.Name.Length; } }

恍如定义和序列化后的结果如下:

图片 18图片 19

public class Student
{
    public Int32 ID;
    public String Name;
    [XmlIgnore]
    public Int32 NameLength { get { return this.Name.Length; } }
}

View Code

图片 20图片 21

<?xml version="1.0"?>
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ID>1</ID>
  <Name>姓名</Name>
</Student>

View Code

5、[XmlArray]:如果要序列化一个数组或者List等,但是用改映射的名称,那么我们便会见为此到[XmlArray]。需要专注的凡,虽然数组等序列化出来的也罢是一个子元素,但是尽量不要为此[XmlElement],否则数组里之各国一个因素相当给对象的直接子元素(除非是仿佛本身序列化成子元素的即老大少还是没有,类似以[XmlText]的情景),下边会被来比。与[XmlElement]当互相仿佛,如果未装参数的说话,那么与不添加特性相同;而针对那个安装参数后,则足以修改子元素的名。例如:

[XmlArray("AllScore")]
public List<Int32> Scores;

恍如定义和序列化后底结果如下:

图片 22图片 23

public class Student
{
    public Int32 ID;
    public String Name;
    [XmlArray("AllScore")]
    public List<Int32> Scores;
    [XmlElement("FamilyMember")]
    public List<String> FamilyNames;
}

View Code

图片 24图片 25

<?xml version="1.0"?>
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ID>1</ID>
  <Name>姓名</Name>
  <AllScore>
    <int>80</int>
    <int>75</int>
    <int>89</int>
  </AllScore>
  <FamilyMember>父亲姓名</FamilyMember>
  <FamilyMember>母亲姓名</FamilyMember>
</Student>

View Code

6、[XmlArrayItem]:上述虽然对数组的称呼进行了照,但是数组里各级一个因素的称谓却并未概念,所以造成的结果是,所有数组里元素的名还是依项目名称来之,比如Int32类的因素的因素名就是int等等,所以我们要采用[XmlArrayItem]特色开展设置,增加及参数后就好射数组里元素的称谓了。例如:

[XmlArray("AllScore")]
[XmlArrayItem("Score")]
public List<Int32> Scores;

接近定义和序列化后的结果如下:

图片 26图片 27

public class Student
{
    public Int32 ID;
    public String Name;
    [XmlArray("AllScore")]
    [XmlArrayItem("Score")]
    public List<Int32> Scores;
}

View Code

图片 28图片 29

<?xml version="1.0"?>
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ID>1</ID>
  <Name>姓名</Name>
  <AllScore>
    <Score>80</Score>
    <Score>75</Score>
    <Score>89</Score>
  </AllScore>
</Student>

View Code

6、[XmlRoot]:对于类似的名目如果一旦投的话,就无可知利用上述任何一个表征了,因为如果对类使用的话会提示“它仅仅于“property,
indexer, field, param,
return”声明遭行之有效”。这时候我们便待[XmlRoot]以此特点,同样的,对那个安参数,即好得对类名称的映射。例如:

[XmlRoot("StudentInfo")]
public class Student { }

上述几个特色除了[XmlIgnore]外边,都还支持设置命名参数,如下图。

图片 30例如[XmlElement]、[XmlArray]当好装Order参数,就是得强制安装子元素出现岗位的先后顺序,例如:

public class Student
{
    [XmlElement(Order = 2)]
    public Int32 ID;
    [XmlElement(Order = 1)]
    public String Name;
}

 

【三、不克序列化的情节】

非像BinaryFormatter,XML序列化是发出诸多东西是无能够序列化的,比如明确的Dictionary,我们实际上可以通过.NET的源代码来查看究竟哪东西不可知队化为XML。通过序列化Dictionary抛来深,可以找到如下是类似的连锁方,在.NET源代码的“Source\Net\3.5.50727.3053\DEVDIV\depot\DevDiv\releases\whidbey\netfxsp\ndp\fx\src\Xml\System\Xml\Serialization\Types.cs”目录下可以找到。

图片 31

依据源代码,可以窥见无可知序列化的发出以下的门类:

1、继承IDictionary接口的花色,这个肯定了。.NET判断是实现了ICollection接口的还使去System.Xml.Serialization.TypeScope.GetDefaultIndexer()判断是否延续了IDictionary接口,如果继续了虽然委来怪。

2、维度大于1之高频组,在System.Xml.Serialization.TypeScope.ImportTypeDesc()里发咬定维度是否超过1,如果维度大于1即使丢弃来十分。

3、ValueType类型,别担心,这个不是因装有值类型的未克吃序列化,源代码里判断的是“type

typeof(ValueType)”,所以特指ValueType类型的不克被序列化。p.s.我才知道还是可以创建ValueType类型的变量。

另外,只要满足第一省里提到的XML序列化的要求的,都能够于序列化,整理如下:

1、定义之接近或结构体或者枚举必须为public,类还是结构体必须来无参的构造方法。比如System.Drawing.Font就无法落实序列化,因为那尚未管参的构造方法。

2、要序列化的字段或性能必须也public,并且不可知吧static,标记为[Obsolete]的不会见于序列化。字段非克为readonlyconst,属性必须以出set和get访问器。比如System.Drawing.Color序列化后非带有其他内容,因为其颇具的国有属性全部才发get访问器,没有set访问器。

 

【四、输出格式的装置】

要对序列化后的XML文件之出口格式来求,比如要修改XML文件的编码、设置XML文件缩进、设置XML的命名空间等等,那么我们好透过XmlWriter来实现我们的渴求。XmlWriter可以由此XmlWriter.Create创建,可以形容副到流动、或者直接写副到文件路径或者写副到一个StringBuilder中。

安XML文件的编码、缩进等得以通过创办XmlWriterSettings来装,例如可以以缩进字符以及换行字符去除以达到减少文件大小的目的。

 1 XmlWriterSettings settings = new XmlWriterSettings();
 2 settings.Encoding = Encoding.ASCII;
 3 settings.IndentChars = "";
 4 settings.NewLineChars = "";
 5 //或者也可以这样
 6 //settings.Indent = false;
 7 //settings.NewLineHandling = NewLineHandling.None;
 8 
 9 XmlWriter xw = XmlWriter.Create(fs, settings);
10 XmlSerializer xs = new XmlSerializer(obj.GetType());
11 xs.Serialize(xw, obj);

倘若对此设置XML命名空间,则可创造XmlSerializerNamespaces,比如可以补加空的命名空间为取消默认设置的命名空间。

1 XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
2 namespaces.Add(String.Empty, String.Empty);
3 
4 //省略部分代码
5 
6 xs.Serialize(xw, obj, namespaces);

 

【相关链接】

  1. XmlSerializer
    类:http://msdn.microsoft.com/zh-cn/library/system.xml.serialization.xmlserializer.aspx
  2. 以.net中序列化读写xml方法的下结论:http://www.cnblogs.com/fish-li/archive/2013/05/05/3061816.html

相关文章

网站地图xml地图