我的存储库有 List<Student>, List<Course>List<Enrolment> 其中 Enrollment 具有 Enrolment.Student 和 Enrolment.Course,它们引用前两个列表中的学生或课程之一。

当我在存储库上使用 XmlSerializer 时,它会输出冗余数据,因为它会序列化每个学生的所有属性 List<Student> 然后再一次,每次提到这些相同的学生 List<Enrolment>. 。我正在寻找一种优雅的方法来解决这个问题。

反序列化后,我可以使用反序列化创建的重复对象实例中的 ID 值来修复引用,但这看起来很黑客。

修复冗余输出的一种方法是 XmlIgnore Enrolment.Student 和 Enrolment.Course,并创建另外两个属性用于序列化 - Enrolment.StudentID 和 Enrolment.CourseID。但是,在反序列化过程中,无法设置 Enrolment.Student 和 Enrolment.Course 的引用(AFAIK),因为反序列化的结果 List<Student>List<Course> 不可用。

我想到的另一种方法是序列化对象层次结构中的较低位置,分别执行每个列表并控制反序列化的顺序 - 我宁愿不这样做。

另一种方法是 XmlIgnore List<Enrolment> 并创建一个注册序列化帮助程序类来初始化 List<Enrolment> 自身反序列化完成后。这看起来需要付出很大的努力。

其他人如何使用 XmlSerializer 序列化/反序列化对同一对象的多个引用?

有帮助吗?

解决方案

喔系列化的痛苦: - > ...

有从来都不是一个通用的解决方案,我想这就是为什么MS剥离出来Silverlight框架的。

我从不依赖于.NET框架的任何自动序列化机制。对于我自己的模型和资料库,我通常都知道,也可以很容易地编程方式确定哪些属性是简单的标者(数字/字符串/等),它们是链接到其他对象(以及它们要么列表)。

有基本上2种方案:

1:我们想要序列/传送仅物体的平信息。在这种情况下我仅传送各个ID为链接到其它对象的属性。然后,接收器可以使随后的查询,以获得他们所需要的所有其他对象。

2:我们希望尽可能多的信息可能,即更深嵌套的XML与几个层次转移,多为直接使用仅仅在XML一些CSS一些报表功能显示的一切。在这种情况下,它实际上是希望是相同的对象将多次被解析成XML树。

有时候,我需要调整的第一个场景一点点,以避免过多的后续查询电话,但通常我相处得很好。即我已经内置到我们的代码库,我们可以指定希望解决时附加的对象,和/或它的某个地方进行配置。

其他提示

存在使用XML序列针对此问题没有解决方案。它没有身份的一个概念,它可能会使用删除重复。

你能做的最好的是从他们引用单独序列化对象池。然后,您可以反序列化后重新创建列表。

顺便说一句,你知道,XmlSerializer的是不特定于C#?

您可以实现接口IXmlSerializable的招生和在方法中WriteXML产生学生,当然XML这将只包含键e.g:

<Student Id="5"/>
<Course Id="6"/>

和在ReadXml方法可以加载来自该引用。您还必须设置XmlIgnore属性为学生和课程属性。

这听起来如何作为一个解决方案:

  1. xmlignore每个二次参考IE入学。
  2. 为每个辅助引用创建一个属性,该属性用于序列化/供应for for该参考的外键 - 带有XML_FK的前缀。例如xml_fk_student&xml_fk_course
  3. 创建一个方法xml_finalizedeserialization,该方法在避难所化后使用这些外键属性加载引用。

您应该/可以使用参考跟踪与datacontract串行器:

//deserilaize:
using(MemoryStream memStmBack = new MemoryStream()) {
  var serializerForth = new DataContractSerializer(
    typeof(YourType),
    null,
    0x7FFF /*maxItemsInObjectGraph*/ ,
    false /*ignoreExtensionDataObject*/ ,
    true /*preserveObjectReferences*/ ,
    null /*dataContractSurrogate*/ );

  byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
  memStmBack.Write(data, 0, data.Length);
  memStmBack.Position = 0;
  var lsBack = (YourType) serializerForth.ReadObject(memStmBack);

}
//serialize...
using(MemoryStream memStm = new MemoryStream()) {
    var serializer = new DataContractSerializer(
      typeof(YourType),
      knownTypes,
      0x7FFF /*maxItemsInObjectGraph*/ ,
      false /*ignoreExtensionDataObject*/ ,
      true /*preserveObjectReferences*/ ,
      null /*dataContractSurrogate*/ );

    serializer.WriteObject(memStm, yourType);

    memStm.Seek(0, SeekOrigin.Begin);

    using(var streamReader = new StreamReader(memStm)) {
        result = streamReader.ReadToEnd();

或者使用

[Serializable]
[DataContract(IsReference = true)]
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top