【问题标题】:Why can't I have a DataMember with `IsRequired=true` if my DataContract is `IsReference=true`如果我的 DataContract 是 `IsReference=true`,为什么我不能有一个带有 `IsRequired=true` 的 DataMember
【发布时间】:2011-03-30 13:46:56
【问题描述】:

我有一个类ClassA,它有一个包含ClassB 类型的属性,它有一个ClassA 类型的字段。当我尝试通过 WCF 序列化它时,由于它的递归性质,我得到了一个异常。解决方案是将IsReference=true 添加到ClassA 的数据合约定义中。

这很好,除了我有ClassA 的成员,它们标有DataMember(IsRequired=true) 属性,一旦我添加了IsReference=true,它就会抱怨事情不能既是IsReference=true,又是@ 987654331@。

我不明白为什么会这样,我想知道是否有解决方法?

我想声明我的数据成员,以便它们在 xml 中需要?

我已经看过this post,但我仍然不清楚答案。如果我想防止发出默认值,那么我可以在 IsRequired=true 旁边使用 EmitDefaultValues=false (这就是我想要做的)。还有其他解决方法吗?

【问题讨论】:

    标签: .net wcf datacontract datamember


    【解决方案1】:

    考虑反序列化场景。您有一堆 DataContractSerializer 正在读取的 XML。假设您正在处理类型 Foo,它被标记为 IsReference=true 和 IsRequired=true。

    序列化程序遇到 Foo 类型的字段 foo1。现在,这意味着 XML 可以说如下内容:

    <foo1 ref="1" /?
    

    序列化程序会将 foo1 反序列化为 null,但请记住它引用了一个它还没有的对象。序列化器继续反序列化剩余的字段。最终,它遇到了像下面这样的另一个字段。啊哈,它看到了 foo1 之前提到的对象——ID 为 1 的对象。

    <foo2 id="1"> <datamember1> ... </datamember1> <datamember2> ... </datamember2> </foo2>
    

    当遇到 id="1" 时,序列化程序返回并修复 foo1 以指向 foo2。

    但是,foo2 可能永远不存在。换句话说, foo1 可能指的是 XML 中其他任何地方都不存在的 ID。在完全反序列化图表的其余部分之前,序列化程序无法确定这一点。

    我希望你开始看到问题。如果一个类型既是 IsReference 又是 IsReequired,则序列化不再可能保证在反序列化期间将遵守该类型的 IsRequired 特性。如果需要的元素不存在,它就不能再快速失败,因为它不能确定它是否存在。

    【讨论】:

    • 感谢 Krisragh,但 IsRequired 标志不允许 Foo 的成员上 而不是在其他类中的 Foo 实例上。您的解释没有说明为什么我不能拥有 Foo 所需的字段,只是因为对 Foo 的引用是共享的。
    • 山姆——实际上,我的解释确实回答了你的问题。我描述的论点以完全相同的方式适用于 Foo 的成员;请注意,在解释中,IsRequired 是在类型本身还是在该类型的成员上都没有关系。排序和引用问题以同样的方式表现出来。
    • 也许我只是昏暗,但我看不出这个论点如何适用于 Foo 的成员。使用 IsRequired=true (以及 EmitDefaultValue=false )我基本上是说,当这种类型包含在 xml 文档中时,该成员的元素必须是部分文档(并且使用 EmitDefaultValue 元素不能为空)。我看不出这对是否引用任何 Foo 实例有何影响。如果文档中存在 Foo 的实例,那么这些属性会影响它的定义方式,不是吗?如果该实例是共享的,那就这样吧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    • 2017-10-31
    相关资源
    最近更新 更多