请原谅我之前的愚昧无知。我已经决定完全分离对象模型和对象的逻辑行为了。
引用使用 Id 保存,即类中不再出现对其他类的直接引用,而仅仅保存 Id。这样在序列化的时候就可以直接保存了。

然而我发现处理 Nullable 类型还是一个很麻烦的问题……
c# – Is there any way for my class to support serialisation as an XML attribute? – Stack Overflow
所以我要自己造轮子!

System.WeakReference<T>
请原谅我之前的愚昧无知。我已经决定完全分离对象模型和对象的逻辑行为了。
引用使用 Id 保存,即类中不再出现对其他类的直接引用,而仅仅保存 Id。这样在序列化的时候就可以直接保存了。

然而我发现处理 Nullable 类型还是一个很麻烦的问题……
c# – Is there any way for my class to support serialisation as an XML attribute? – Stack Overflow
所以我要自己造轮子!
重新造轮子 TT
ref = CXuesong/XSerializer/
欢迎围观 TT
最近一直在考虑以下问题:
在使用 `XmlSerializer `以精确控制 XML 格式的同时
其中,第二个问题似乎可以使用 `DataContractSeriallizer` 来解决。然而 `DataContractSeriallizer` 会在生成 XML 时自行为对象确定 Id,并使用 `z:Id` 和`z:Ref` 来表示 Id 和 Id 引用。正如在前几篇文章中提到的那样,`DataContractSeriallizer` 对 XML 结构的控制自由度是十分有限的。
那么,如何才能圆满地解决这些问题呢?
我觉得,可以自己造轮子了。
通常来说,当你想更加精确地控制生成的 XML 时,可以使用 `XmlSerializer`。如果你对生成的 XML 格式并不在意(例如所有的属性/字段均会以元素的形式保存),同时想保留对象的所有信息(包括私有属性/字段),则可以使用 `DataContractSerializer`。 继续阅读“在 XmlSerializer 与 DataContractSerializer 之间抉择”
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var f = new XmlSerializer(typeof(TestClass));
using (var sw = new StringWriter())
{
f.Serialize(sw, new TestClass());
using (var sr = new StringReader(sw.ToString()))
{
var bt = (TestClass) f.Deserialize(sr);
Console.WriteLine(bt.ListIdentical());
}
}
}
}
public class TestClass
{
private List<int> PrivateList;
public List<int> MyList;
public bool ListIdentical()
{
return PrivateList == MyList;
}
public TestClass()
{
PrivateList = new List<int>() { 123, 567 };
MyList = PrivateList;
}
}
}
运行结果为 `True` 。实际上,如果把 `MyList` 换成只读属性,只要其值非 null / Nothing,则程序仍可以正常运行。
也就是说,反序列化过程复用了已有的集合实例。 继续阅读“XmlSerializer 测试 2”
测试源代码如下,使用 VS2013 编写。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var f = new XmlSerializer(typeof(TestClass), new[] { typeof(DerivedClass1), typeof(ChildNS.DerivedClass1) });
var ns = new XmlSerializerNamespaces();
ns.Add("ns", "http://yourcompany.org/schemas/ns");
ns.Add("nsc", "http://yourcompany.org/schemas/ns/child");
ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
using (var sw = new StringWriter())
{
f.Serialize(sw, new TestClass(), ns);
Console.WriteLine(sw.ToString());
}
}
}
public class TestClass
{
public BaseClass BaseTest = new BaseClass();
public BaseClass BaseTest1 = new DerivedClass1();
[XmlElement(Namespace = "http://yourcompany.org/schemas/ns/child")]
public BaseClass BaseTest2 = new ChildNS.DerivedClass1();
public BaseClass[] BaseArray1 = {new BaseClass(), new DerivedClass1()};
[XmlArrayItem(typeof(BaseClass), IsNullable = true),
XmlArrayItem(typeof(DerivedClass1), IsNullable = true),
XmlArrayItem(typeof(DerivedClass2), IsNullable = true)]
public BaseClass[] BaseArray2 =
{
new BaseClass(), new DerivedClass1(),
null, new DerivedClass2()
};
[XmlArrayItem(typeof(BaseClass), IsNullable = true)]
public BaseClass[] BaseArray3 =
{
new BaseClass(),
new DerivedClass1(), null, new DerivedClass2()
};
[XmlArrayItem(typeof(BaseClass))]
public List<BaseClass> BaseList = new List<BaseClass> { new BaseClass(), new DerivedClass1() };
[XmlElement(IsNullable = true)]
public object NullObject1 = null;
public object NullObject2 = null;
//public IEnumerable BaseListEnumerable = new List<BaseClass> { new BaseClass(), new DerivedClass1() };
}
public class BaseClass
{
[XmlAttribute("value1", Namespace = "http://yourcompany.org/schemas/ns")]
public int Value1;
[XmlAttribute("value2")]
public int Value2;
[XmlAttribute("value3", Namespace = "http://yourcompany.org/schemas/ns")]
public int Value3;
}
public class DerivedClass1 : BaseClass
{
[XmlAttribute("value4", Namespace = "http://yourcompany.org/schemas/ns")]
public int Value4;
}
public class DerivedClass2 : BaseClass
{
[XmlAttribute("value4", Namespace = "http://yourcompany.org/schemas/ns")]
public int Value4;
}
namespace ChildNS
{
//为类型强制指定 XML 名称,以及命名空间,以避免命名冲突。
[XmlType("ChildDerivedClass", Namespace = "http://yourcompany.org/schemas/ns/child")]
public class DerivedClass1 : BaseClass
{
public int Value5;
}
}
}
运行结果如下
<?xml version="1.0" encoding="utf-16"?>
<TestClass xmlns:ns="http://yourcompany.org/schemas/ns" xmlns:nsc="http://yourcompany.org/schemas/ns/child" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<BaseTest ns:value1="0" value2="0" ns:value3="0" />
<BaseTest1 xsi:type="DerivedClass1" ns:value1="0" value2="0" ns:value3="0" ns:value4="0" />
<nsc:BaseTest2 xsi:type="nsc:ChildDerivedClass" ns:value1="0" value2="0" ns:value3="0">
<nsc:Value5>0</nsc:Value5>
</nsc:BaseTest2>
<BaseArray1>
<BaseClass ns:value1="0" value2="0" ns:value3="0" />
<BaseClass xsi:type="DerivedClass1" ns:value1="0" value2="0" ns:value3="0" ns:value4="0" />
</BaseArray1>
<BaseArray2>
<BaseClass ns:value1="0" value2="0" ns:value3="0" />
<DerivedClass1 ns:value1="0" value2="0" ns:value3="0" ns:value4="0" />
<DerivedClass2 ns:value1="0" value2="0" ns:value3="0" ns:value4="0" />
</BaseArray2>
<BaseArray3>
<BaseClass ns:value1="0" value2="0" ns:value3="0" />
<BaseClass xsi:type="DerivedClass1" ns:value1="0" value2="0" ns:value3="0" ns:value4="0" />
<BaseClass xsi:nil="true" />
<BaseClass xsi:type="DerivedClass2" ns:value1="0" value2="0" ns:value3="0" ns:value4="0" />
</BaseArray3>
<BaseList>
<BaseClass ns:value1="0" value2="0" ns:value3="0" />
<BaseClass xsi:type="DerivedClass1" ns:value1="0" value2="0" ns:value3="0" ns:value4="0" />
</BaseList>
<NullObject1 xsi:nil="true" />
</TestClass>
可以看出,
cite=https://msdn.microsoft.com/ZH-CN/library/vstudio/2baksw0z.aspx
XmlArrayItemAttribute 的另一种用法是,允许序列化派生类。 例如,可将派生自 Employee 的另一个名为 Manager 的类添加至上一示例中。 如果没有应用 XmlArrayItemAttribute,代码将在运行时失败,原因是无法识别派生类类型。 若要解决这个问题,每次为每个可接受类型(基类和派生类)设置 Type 属性时,需要应用该特性两次。
public class Group{ [XmlArrayItem(Type = typeof(Employee)), XmlArrayItem(Type = typeof(Manager))] public Employee[] Employees; } public class Employee{ public string Name; } public class Manager:Employee{ public int Level; }序列化实例可能如下所示。
<Group> <Employees> <Employee> <Name>Haley</Name> </Employee> <Employee xsi:type = "Manager"> <Name>Ann</Name> <Level>3</Level> <Employee> </Employees> </Group>
然而实际情况不一样…… 继续阅读“MSDN中“(使用 XmlArrayItemAttribute 限定)序列化派生类”一节中的示例可能与实际有出入”