gpt4 book ai didi

c# - ShouldSerialize*() 与 *指定的条件序列化模式

转载 作者:IT王子 更新时间:2023-10-29 04:47:34 25 4
gpt4 key购买 nike

我知道 ShouldSerialize* 模式和 *Specified 模式以及它们是如何工作的,但是两者之间有什么区别吗?

当某些事情应该有条件地序列化时,使用一种方法与另一种方法是否有任何“问题”?

这个问题针对XmlSerializer的用法,但也欢迎有关此主题的一般信息。

关于这个主题的信息很少,所以可能是因为它们执行完全相同的目的,这是一种风格选择。但是,.NET 实现者会通过反射分析类并查找任一/两种模式以确定生成的序列化程序的行为方式,这似乎很奇怪,因为它会减慢序列化程序的生成速度,除非它只是向后兼容的工件。

编辑:对于那些不熟悉这两种模式的人,如果 *Specified属性(property)或ShouldSerialize*方法返回true,然后该属性被序列化。

public string MyProperty { get; set; }

//*Specified Pattern
[XmlIgnore]
public bool MyPropertySpecified { get{ return !string.IsNullOrWhiteSpace(this.MyProperty); } }

//ShouldSerialize* Pattern
public bool ShouldSerializeMyProperty()
{
return !string.IsNullOrWhiteSpace(this.MyProperty);
}

最佳答案

{propertyName}Specified的意图模式记录在 XML Schema Binding Support: MinOccurs Attribute Binding Support 中.添加它是为了支持 XSD 架构元素,其中:

  • <element> 元素参与。
  • 最小发生次数 为零。
  • maxOccurs 属性指示单个实例。
  • 数据类型转换为值类型。

  • 在这种情况下, xsd.exe /classes 将自动生成(或者您可以手动生成)与架构元素同名的属性和 {propertyName}Specified boolean get/set 属性,用于跟踪元素是否在 XML 中遇到并应序列化回 XML。如果遇到元素, {propertyName}Specified设置为 true , 否则 false .因此,反序列化的实例可以确定原始 XML 中的属性是否未设置(而不是显式设置为其默认值)。

    反过来也用于模式生成。如果您使用一对与上述模式匹配的属性定义 C# 类型,则使用 xsd.exe生成相应的XSD文件,一个合适的 minOccurrs将被添加到架构中。例如,给定以下类型:
    public class ExampleClass
    {
    [XmlElement]
    public decimal Something { get; set; }

    [XmlIgnore]
    public bool SomethingSpecified { get; set; }
    }

    将生成以下模式,反之亦然:
    <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="ExampleClass" nillable="true" type="ExampleClass" />
    <xs:complexType name="ExampleClass">
    <xs:sequence>
    <xs:element minOccurs="0" maxOccurs="1" name="Something" type="xs:decimal" />
    </xs:sequence>
    </xs:complexType>
    </xs:schema>

    请注意,虽然 xsd.exe记录仅用于自动生成 {propertyName}Specified值类型属性的属性, XmlSerializer当手动用于引用类型属性时,将遵循模式。

    你可能会问,为什么 xsd.exe不绑定(bind)到 Nullable<T>在这种情况下?也许是因为:
  • 可空值用于支持 xsi:nil="true" 属性代替。见 Xsi:nil Attribute Binding Support .
  • Nullables 直到 .Net 2.0 才被引入,所以也许现在使用它们为时已晚?

  • 您需要注意这种模式,因为 xsd.exe有时会自动为您生成它,但是属性与其之间的交互 Specified属性很奇怪,容易产生错误。你可以把你的类中的所有属性都填满,然后序列化成XML,然后丢失一切,因为你还没有设置set对应的 Specified属性到 true .这个“陷阱”不时出现在这里,参见例如 this questionthis one also .

    此模式的另一个“问题”是,如果您需要使用不支持此模式的序列化程序来序列化您的类型,您 5 月 想在序列化过程中手动抑制此属性的输出,以及 可能会需要在反序列化时手动设置。由于每个序列化程序可能都有自己的自定义机制来抑制属性(或根本没有机制!),随着时间的推移,这样做会变得越来越繁重。

    (最后,我有点惊讶您的 MyPropertySpecified 在没有 setter 的情况下也能成功运行。我似乎记得 .Net 2.0 的一个版本,其中缺少 {propertyName}Specified setter 会导致抛出异常。但它不再是可以在以后的版本上重现,而且我没有 2.0 可以测试。所以这可能是第三个陷阱。)

    支持 ShouldSerialize{PropertyName}()方法记录在 Properties in Windows Forms Controls: Defining Default Values with the ShouldSerialize and Reset Methods 中.如您所见,文档位于 MSDN 的 Windows 窗体部分,而不是 XmlSerializer部分,所以它实际上是半隐藏的功能。我不知道为什么支持这种方法和 Specified属性都存在于 XmlSerializer . ShouldSerialize.Net 1.1 中引入我相信在 .Net 2.0 中添加了 MinOccurs 绑定(bind)支持,所以早期的功能可能不太符合 xsd.exe 的需求(或品味)。开发小组?

    因为它是一个方法而不是一个属性,所以它缺少 {propertyName}Specified 的“陷阱”。图案。它在实践中似乎也更受欢迎,并已被其他序列化程序采用,包括:
  • Json.NET
  • protobuf-net (声称 supports both patterns 。)

  • 那么,该使用哪种模式?
  • xsd.exe生成 {propertyName}Specified自动为您提供属性,或者您的类型需要跟踪特定元素是否出现在 XML 文件中,或者您需要自动生成的 XSD 来指示某个值是可选的,请使用此模式并注意“陷阱” ”。
  • 否则,使用 ShouldSerialize{PropertyName}()图案。它有更少的陷阱,可能会得到更广泛的支持。
  • 关于c# - ShouldSerialize*() 与 *指定的条件序列化模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37838640/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com