【题外话】

先前纵然常用.NET中的系列化,不过常用的BinaryFormatter,也正是二进制文件的体系化,却鲜用XML的类别化。对于XML系列化,.NET中一样提供了3个充足方便的工具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的选取,其实万分不难,只要求几行代码即可达成将3个对象体系化:

图片 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,有3个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]:要是1性情质或字段大家不期望种类化(比如该属性是经过其它字段获取到的,并从未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]:如若须求系列化1个数组大概List等,可是急需修改映射的称谓,那么我们就会用到[XmlArray]。须求小心的是,尽管数组等系列化出来的也是1个子元素,不过尽量不要用[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]:上述即便对数组的名称举办了炫耀,可是数组里每3个要素的名目却从不定义,所以导致的结果是,全体数组里成分的称号都以根据项目名称来的,比如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

依照源代码,能够发现不可能连串化的有以下的档次:

壹 、继承IDictionary接口的类型,那个分明了。.NET判断凡是达成了ICollection接口的都要去System.Xml.Serialization.TypeScope.GetDefaultIndexer()判断是还是不是持续了IDictionary接口,假使继续了则抛出极度。

贰 、维度大于1的数组,在System.Xml.Serialization.TypeScope.ImportTypeDesc()里有咬定维度是还是不是超出1,如果维度大于1就抛出特别。

三 、ValueType类型,别担心,那几个不是指具有值类型的不可能被系列化,源代码里判断的是“type

typeof(ValueType)”,所以特指ValueType类型的不可能被类别化。p.s.我才知晓还能创设ValueType类型的变量。

除此以外,只要满足第四节里提到的XML系列化的渴求的,都能被体系化,整理如下:

壹 、定义的类如故结构体只怕枚举必须为public,类或结构体必须有无参的构造方法。比如System.Drawing.Font就不能够兑现连串化,因为其尚未无参的构造方法。

贰 、要体系化的字段或性质必须为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地图