好吧……我决定自己实现 XmlSerializer 了

重新造轮子 TT

ref = CXuesong/XSerializer/

欢迎围观 TT

最近一直在考虑以下问题:

在使用 XmlSerializer 以精确控制 XML 格式的同时

  1. 如何序列化 Nullable<T> 格式的数据,并将其保存为 XML 属性(而非元素)?
  2. 如何序列化对象的引用,使其不会以多个副本的形式保存?
  3. 在实现上面这两点(尤其是第一点)的时候,不会引入其他的公共辅助属性。
    (例如对于第一点,可以通过一个辅助属性,实现 Nullable<T>string 之间的转换,而 string 是可以保存为 XML 属性的。)

其中,第二个问题似乎可以使用 DataContractSeriallizer 来解决。然而 DataContractSeriallizer 会在生成 XML 时自行为对象确定 Id,并使用 z:Idz:Ref 来表示 Id 和 Id 引用。正如在前几篇文章中提到的那样,DataContractSeriallizer 对 XML 结构的控制自由度是十分有限的。

那么,如何才能圆满地解决这些问题呢?

我觉得,可以自己造轮子了。

 

XmlSerializer 测试 2

集合

运行结果为 True 。实际上,如果把 MyList 换成只读属性,只要其值非 null / Nothing,则程序仍可以正常运行。

也就是说,反序列化过程复用了已有的集合实例。 继续阅读“XmlSerializer 测试 2”

XmlSerializer 测试

测试源代码如下,使用 VS2013 编写。

运行结果如下

可以看出,

  1. XmlArrayItem(Attribute)XmlElement 等相关特性中指定 IsNullable = true 可以使得当前为 null / Nothing 的元素在序列化时产生一个包含 xsi:nil="true" 特性的 XML 元素。
  2. 在特性中指定元素的命名空间时,应当指定命名空间的 URI,尽管可以稍后在 XmlSerializerNamespaces 中为这些 URI 指定对应的命名空间前缀。
  3. 需要序列化派生类时,总是 需要通过 XmlInclude 特性,或者通过 XmlSerializer 的构造函数显式声明序列化过程中可能用到的派生类。
  4.  数组的序列化:可以通过 XmlArrayItem 特性声明数组中可能包含的派生类类型。这些类型在序列化时会使用与之对应的元素名。如果存在未在 XmlArrayItem 中声明的派生类,而其基类在 XmlArrayItem 中声明过,则会使用基类对应的元素名,外加 xsi:type 特性声明实际派生类的类型。(关于这一点,可以参阅另一篇文章:MSDN中“(使用 XmlArrayItemAttribute 限定)序列化派生类”一节中的示例可能与实际有出入
  5. 我该滚去修改以前的代码了。

MSDN中“(使用 XmlArrayItemAttribute 限定)序列化派生类”一节中的示例可能与实际有出入

cite=https://msdn.microsoft.com/ZH-CN/library/vstudio/2baksw0z.aspx

XmlArrayItemAttribute 的另一种用法是,允许序列化派生类。 例如,可将派生自 Employee 的另一个名为 Manager 的类添加至上一示例中。 如果没有应用 XmlArrayItemAttribute,代码将在运行时失败,原因是无法识别派生类类型。 若要解决这个问题,每次为每个可接受类型(基类和派生类)设置 Type 属性时,需要应用该特性两次。

序列化实例可能如下所示。

然而实际情况不一样…… 继续阅读“MSDN中“(使用 XmlArrayItemAttribute 限定)序列化派生类”一节中的示例可能与实际有出入”

与语言标识相关的两个基本函数

今天回趟家,顺便看看以前的代码……