ShouldSerialize*() 与 *指定的条件序列化模式 [英] ShouldSerialize*() vs *Specified Conditional Serialization Pattern

查看:25
本文介绍了ShouldSerialize*() 与 *指定的条件序列化模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am aware of both of the ShouldSerialize* pattern and the *Specified pattern and how they work, but is there any difference between the two?

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

Are there any "gotchas" using one method vs the other when certain things should be serialized conditionally?

此问题特定于 XmlSerializer 的使用,但也欢迎提供有关此主题的一般信息.

This question is specific to the usage of XmlSerializer, but general information regarding this topic is welcome as well.

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

There is very little information on this topic out there, so it may be because they perform the exact same purpose and it's a style choice. However, it seems strange that the .NET implementers would analyze the class via reflection and look for either/both patterns to determine how the generated serializer behaves since it slows down the generation of the serializer unless it's just a backwards compatibility artifact.

对于那些不熟悉这两种模式的人,如果 *Specified 属性或 ShouldSerialize* 方法返回 true,则该属性为连载.

For those unfamiliar with the two patterns if either the *Specified property or ShouldSerialize* method returns true, then that property is serialized.

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 架构绑定支持:MinOccurs 属性绑定支持.添加它是为了支持 XSD 架构元素,其中:

The intent of the {propertyName}Specified pattern is documented in XML Schema Binding Support: MinOccurs Attribute Binding Support. It was added to support an XSD schema element in which:

  • 涉及元素.
  • minOccurs 为零.
  • ma​​xOccurs 属性指定单个实例.
  • 数据类型转换为值类型.
  • The <element> element is involved.
  • minOccurs is zero.
  • The maxOccurs attribute dictates a single instance.
  • The data type converts to a value type.

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

In this case, xsd.exe /classes will automatically generate (or you can manually generate) a property with the same name as the schema element and a {propertyName}Specified boolean get/set property that tracks whether the element was encountered in the XML and should be serialized back to XML. If the element is encountered, {propertyName}Specified is set to true, otherwise false. Thus the deserialized instance can determine whether the property was unset (rather than explicitly set to its default value) in the original XML.

模式生成也实现了逆向.如果你定义了一个 C# 类型,有一对与上面的模式匹配的属性,然后使用 xsd.exe 生成一个对应的 XSD 文件,一个适当的 minOccurrs 将被添加到模式.例如,给定以下类型:

The inverse is also implemented for schema generation. If you define a C# type with a pair of properties matching the pattern above, then use xsd.exe to generate a corresponding XSD file, an appropriate minOccurrs will be added to the schema. For instance, given the following type:

public class ExampleClass
{
    [XmlElement]
    public decimal Something { get; set; }

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

将生成以下模式,反之亦然:

The following schema will be generated, and vice versa:

<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 将手动用于引用类型属性时,请遵守模式.

Note that, while xsd.exe is documented only to generate automatically a {propertyName}Specified property for value type properties, XmlSerializer will respect the pattern when used manually for reference type properties.

您可能会问,在这种情况下,为什么 xsd.exe 不绑定到 Nullable?可能是因为:

You might ask, why does xsd.exe not bind to a Nullable<T> in this case? Perhaps because:

您需要注意这种模式,因为 xsd.exe 有时会自动为您生成它,但是属性与其 Specified 属性之间的交互很奇怪并且容易产生错误.你可以填满你的类中的所有属性,然后序列化为XML并丢失一切,因为你还没有设置相应的Specified属性设置为true.这个陷阱"不时出现在这里,参见例如这个问题这个也是.

You need to be aware of this pattern because xsd.exe will sometimes generate it for you automatically, however the interaction between a property and its Specified property is weird and liable to produce bugs. You can fill up all the properties in your class, then serialize to XML and lose everything because you didn't also set set the corresponding Specified properties to true. This "gotcha" comes up here from time to time here, see e.g. this question or this one also.

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

Another "gotcha" with this pattern is that, if you need to serialize your type with a serializer that does not support this pattern, you may want to manually suppress output of this property during serialization, and probably will need to manually set it during deserialization. Since each serializer may have its own custom mechanism for suppressing properties (or no mechanism at all!), doing this can become more and more burdensome over time.

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

(Finally, I'm a little surprised that your MyPropertySpecified works successfully without a setter. I seem to recall a version of .Net 2.0 in which a missing {propertyName}Specified setter would cause an exception to be thrown. But it's no longer reproducible on later versions, and I don't have 2.0 to test. So that might be a third gotcha.)

ShouldSerialize{PropertyName}() 方法的支持记录在 Windows 窗体控件中的属性:使用 ShouldSerialize 和 Reset 方法定义默认值.正如您所看到的,文档位于 MSDN 的 Windows 窗体部分而不是 XmlSerializer 部分,因此它实际上是半隐藏功能.我不知道为什么在 XmlSerializer 中都支持此方法和 Specified 属性.ShouldSerialize 是在 中引入的.Net 1.1 并且我相信 MinOccurs 绑定支持已添加到 .Net 2.0,所以早期的功能可能不太符合 xsd.exe 开发的需求(或品味)团队?

Support for the ShouldSerialize{PropertyName}() method is documented in Properties in Windows Forms Controls: Defining Default Values with the ShouldSerialize and Reset Methods. As you can see the documentation is in the Windows Forms section of MSDN not the XmlSerializer section, so it is, in fact, semi-hidden functionality. I have no idea why support for this method and the Specified property both exist in XmlSerializer. ShouldSerialize was introduced in .Net 1.1 and I believe that MinOccurs binding support was added in .Net 2.0, so perhaps the earlier functionality didn't quite meet the needs (or taste) of the xsd.exe development team?

因为它是一个方法而不是一个属性,所以它缺少 {propertyName}Specified 模式的陷阱".它在实践中似乎也更受欢迎,并已被其他序列化程序采用,包括:

Because it is a method not a property, it lacks the "gotchas" of the {propertyName}Specified pattern. It also seems to be more popular in practice, and has been adopted by other serializers including:

  • Json.NET
  • protobuf-net (which claims to supports both patterns.)

那么,该使用哪种模式?

So, which pattern to use?

  1. 如果 xsd.exe 自动为您生成一个 {propertyName}Specified 属性,或者您的类型需要跟踪特定元素是否出现在XML 文件,或者您需要自动生成的 XSD 来指示某个值是可选的,请使用此模式并注意问题".

  1. If xsd.exe generates a {propertyName}Specified property for you automatically, or your type needs to track whether a specific element appeared or not in the XML file, or you need your auto-generated XSD to indicate that a certain value is optional, use this pattern and watch out for the "gotchas".

否则,请使用 ShouldSerialize{PropertyName}() 模式.它的问题更少,而且可能得到更广泛的支持.

Otherwise, use the ShouldSerialize{PropertyName}() pattern. It has fewer gotchas and may be more widely supported.

这篇关于ShouldSerialize*() 与 *指定的条件序列化模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆