我认为,这将是一个小问题,可以立即找到答案,但是互联网以某种方式证明了我的假设是错误的。
我有一个包含几个实体的模型,这些实体之间具有所有可能的关联(1到1、1到很多,很多到很多,聚合,组成等)。为了简单起见,让我们以这个例子为例。我们有一个Person类和一个Car类。一个人可以拥有多辆汽车,但是一辆汽车只能属于一个人(因此,一对多关系)。现在,在Person中创建一个List / ArrayList来跟踪他/她的汽车将非常简单。但是,我也想跟踪车主。因此,这些类如下所示:
[Serializable]
public class Person
{
[XmlElement]
public List<Car> Cars { get; set; }
[XmlAttribute]
public string Name { get; set; }
public Person()
{
Cars = new List<Car>();
}
}
[Serializable]
public class Car
{
[XmlElement]
public Person Owner { get; set; }
[XmlAttribute]
public string Type { get; set; }
public Car()
{
}
}
但是,我相信,这种结构会在Xml文件中引起无限循环,如下所示:
<Person name="John Doe">
<Cars>
<Car type="Ford">
<Owner>
<Person name="John Doe">
<Cars>
<Car type="Ford">
<Owner>
<Person name="John Doe">
... etc.
我什至尝试了它,并且在序列化过程中得到了“您需要将XmlChoiceIdentifierAttribute添加到'Owner'成员。” 例外。
因此,我有几个问题:1.有没有办法防止序列化循环?2.如果不是,是否必须为每个类编写自己的序列化器?3.此映射可以吗?还是有其他/更好的方法?我考虑过一个中央的“映射器”类,该类将基于ID返回所需的对象...但是同样,这可以通过SQL来完成。而且我想避免使用SQL(因为使应用程序保持轻量化)。
XmlSerializer
是树序列化器,而不是图形序列化器。最好的选择是避免在序列化过程中向后导航,例如,通过执行以下操作:
[XmlIgnore]
public Person Owner { get; set; }
(“父母”和“所有者”几乎总是向后导航)
不幸的是,XmlSerializer
不支持序列化后的回调,否则可以添加如下内容:
[WhateverOnAfterDeserialized]
public void OnAfterDeserialized(...) {
foreach(var car in cars) car.Owner = this;
}
其他一些序列化程序确实支持序列化回调,但是通过这种标记,那些其他序列化程序也可能也支持全图序列化。例如,DataContractSerializer
可以同时支持回调和完整图形,但对xml的控制要少得多。
另一种选择是拥有一个自定义集合类型,该类型在您添加/删除时维护父属性。例如:
public class Person
{
private readonly CarCollection cars;
public Person() {
cars = new CarCollection(this);
}
[XmlElement]
public CarCollection Cars { get { return cars; } }
...
}
与(中CarCollection
):
// add code...
innerList.Add(value);
value.Parent = parent; // this is the field stored in the constructor
就个人而言,我认为这可能是过大的。
另一个选择是简单地添加一个反序列化后调用的修复方法,该方法可以执行所有必要的操作(并向下层叠):
public void FixupAfterDeserializer() {
foreach(var car in cars) car.Parent = this;
}
请注意,您将必须手动调用它。
最后,请注意,[Serializable]
对于,这不是必需的XmlSerializer
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句