.NET XmlSerializer 和对同一对象的多个引用

发布于 2024-08-17 08:02:11 字数 996 浏览 3 评论 0原文

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

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

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

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

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

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

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

My repository has List<Student>, List<Course> and List<Enrolment> where an Enrolment has Enrolment.Student and Enrolment.Course which are references one of the students or courses in the two previous lists.

When I use XmlSerializer on my repository it outputs redundant data as it serializes all properties of each student in List<Student> then again for every reference to those same students in List<Enrolment>. I'm looking for an elegant way to solve this.

After deserialization I can fix the references using the ID values in the duplicate object instances created by the deserialization but this seems hackish.

One method to fix the redundant output is to XmlIgnore Enrolment.Student and Enrolment.Course and create two more properties for serialization - Enrolment.StudentID and Enrolment.CourseID. However during deserialization, the references for Enrolment.Student and Enrolment.Course cannot be set (AFAIK) since the results of deserialization of List<Student> and List<Course> are not available.

Another method I thought of is to serialize lower down in my object hierarchy doing each of my Lists separately and controlling the order of deserialization - I rather not do this.

Another method would be to XmlIgnore List<Enrolment> and create an enrolment serialization helper class that initializes List<Enrolment> after the deserialization of itself is complete. This seems like a lot of effort.

How do other people serialize/deserialize multiple references to the same object using XmlSerializer?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

鲸落 2024-08-24 08:02:11

哦连载的痛苦:-> ...

对此从来没有一个通用的解决方案,我想这就是为什么 MS 将其从 Silverlight 框架中剥离出来的原因。

我从不依赖 .net 框架的任何自动序列化机制。对于我自己的模型和存储库,我通常知道或可以轻松地以编程方式确定哪些属性是简单的标量属性(数字/字符串/等),哪些属性是到其他对象的链接(以及哪些是两者的列表)。

基本上有两种情况:

1:我们只想序列化/传输对象的平面信息。在这种情况下,我仅传输链接到其他对象的属性的相应 ID。然后接收者可以进行后续查询以获取他们需要的所有其他对象。

2:我们希望传输尽可能多的信息,即具有多个级别的更深层次的嵌套 XML,主要用于某些仅使用 XML 上的 CSS 直接显示所有内容的报告功能。在这种情况下,实际上需要将相同的对象多次解析到 XML 树中。

有时我需要稍微调整第一个场景,以避免过多的后续查询调用,但通常我相处得很好。即,我已将其内置到我们的代码库中,我们可以指定何时要解析哪些附加对象,和/或在某处配置它。

Oh the pains of serialization :-> ...

There was never a generic solution for this, I guess that's why MS stripped it out of the Silverlight framework.

I never rely on any automatic serialization mechanisms of the .net framework. For my own models and repositories, I usually know or can easily programmatically determine which properties are simple scalar ones (numbers/strings/etc) and which are links to other objects (as well as which are lists of either).

There are basically 2 scenarios:

1: We want to serialize/transfer only the flat information of objects. In that case I transfer only the respective IDs for properties that link to other objects. The receiver can then make subsequent queries to get all other objects they need.

2: We want to transfer as much information as possible, i.e. deeper nested XML with several levels, mostly for some reporting functionality displaying everything directly using merely some CSS on the XML. In that case, it is actually desired that objects that are the same will be resolved multiple times into the XML tree.

Sometimes I need to tweak the first scenario a little bit in order to avoid too many subsequent query calls, but usually I get along very well. I.e. I have built into our code base that we can specify which additional objects we want to resolve when, and/or it's configured somewhere.

旧竹 2024-08-24 08:02:11

没有使用 XML Serializer 解决此问题的方法。它没有可用于删除重复的身份概念。

您能做的最好的事情就是将对象池与其引用分开序列化。然后,您可以在反序列化后重新创建列表。

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

There is no solution for this issue using the XML Serializer. It does not have a concept of identity that it might use to remove duplication.

The best you can do is to serialize the pool of objects separately from their references. You could then recreate your lists after deserialization.

BTW, are you aware that the XmlSerializer is not specific to C#?

禾厶谷欠 2024-08-24 08:02:11

您可以实现接口 IXmlSerialized 到 Enrollment,并在 WriteXml 方法中生成学生和课程 XML,其中仅包含键,例如:

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

在 ReadXml 方法中您可以从中加载引用。您还必须将 XmlIgnore 属性设置为 Student 和 Course 属性。

You can implement interface IXmlSerializable to Enrolment and in WriteXml method generate student and course XML which will contains only keys e.g.:

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

and in ReadXml method you can load references from this. You must also set XmlIgnore attribute to Student and Course property.

九厘米的零° 2024-08-24 08:02:11

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

  1. XMLIgnore every secondary
    参考即 Enrolment.Student &
    Enrolment.Course
  2. 为每个中学创建一个属性
    参考用于
    序列化/反序列化外键
    作为参考 - 前缀
    使用 XML_FK。例如 XML_FK_Student &
    XML_FK_Course
  3. 创建一个 XML_FinalizeDeserialization 方法,即
    反序列化后调用加载
    使用国外的参考文献
    关键属性。

How does this sound as a solution:

  1. XMLIgnore each secondary
    reference ie Enrolment.Student &
    Enrolment.Course
  2. create a property for each secondary
    reference that is used to
    serialize/deserialize a foreign key
    for that reference instead - Prefix
    with XML_FK. eg XML_FK_Student &
    XML_FK_Course
  3. Create a method XML_FinalizeDeserialization that is
    called after deserialization to load
    the references using those foreign
    key properties.
生生漫 2024-08-24 08:02:11

您应该/可以将引用跟踪与数据契约序列化器一起使用:

//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)]

You should/can use Reference Tracking with the datacontract serializer:

//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();

Or use

[Serializable]
[DataContract(IsReference = true)]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文