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

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

问题描述

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



是否有任何陷阱使用一种方法相较于其他当某些事情应该有条件地序列化?



这问题是特定于的XmlSerializer 的用法,但关于这个话题的一般信息是值得欢迎的,以及



有关于这个主题的信息很少在那里,所以这可能是因为他们执行相同的目的,这是一个风格的选择。然而,似乎奇怪的是,.NET实施者将通过反射分析类并查找非此即彼/两个模式,以确定所产生的序列化的行为方式,因为它减缓了序列化的产生,除非它只是一个向后兼容神器。



编辑:对于那些不熟悉的两个模式如果 *指定属性或 ShouldSerialize * 方法返回true,则该属性序列化。

 公共字符串myProperty的{搞定;组; } 

// *指定模式
[XmlIgnore]
公共BOOL MyPropertySpecified {{返回string.IsNullOrWhiteSpace(this.MyProperty)!; }}

// ShouldSerialize *模式
公共BOOL ShouldSerializeMyProperty()
{
返回string.IsNullOrWhiteSpace(this.MyProperty)!;
}


解决方案

的意图 {} propertyName的指定模式在记录XML架构绑定支持:的minOccurs属性绑定支持。它被添加到支持XSD架构元素,其中:




  • <组件> 元素参与。

  • 的minOccurs 是零。

  • maxOccurs的属性决定了一个实例。

  • 的数据类型转换为值类型。



在这种情况下, XSD.EXE 将自动生成(您也可以手动生成)具有相同名称的架构元素和属性 {} propertyName的指定布尔获取/设置属性的 / em>的。如果遇到元素, {propertyName的}指定设置为真正,否则。因此,反序列化的实例都无法确定财产是否被清除的,或明确设置为默认值,反序列化过程。



请注意,虽然XSD.EXE只记录生成自动将 {propertyName的}指定属性值类型的属性,同样的模式可以手动用于引用类型的属性。



您可能会问,为什么不XSD.EXE绑定在这种情况下,可为空?也许是因为:





您需要了解这种模式,因为XSD.EXE有时会自动生成它适合你,但一个属性,它的指定之间的相互作用属性是奇怪,容易产生错误。你可以在你的类填满了所有的属性,然后序列化到XML和失去的所有的,因为你没有还设置设置相应的指定属性到真正。这种疑难杂症这里这里来了,不时见例如这个问题或的这其中也的。



另一个疑难杂症这种模式是这样的,如果你需要使用不支持此模式的一个串行序列化你的类型,您可以要序列化过程中手动抑制这种属性的输出,和可能需要反序列化过程中手动设置。由于每个串行器可以具有用于抑制属性其自己的自定义机制(或没有机制在所有!),这样做可以变得越来越繁琐随时间



(最后我有点惊讶,你的 MyPropertySpecified 成功作品,未经似的。我似乎记得一个版本的.NET 2.0,其中缺少 {propertyName的}指定 setter方法​​会导致一个异常被抛出,但它已经不再在以后的版本中重复性好,我没有2.0来测试,所以这可能是第三个疑难杂症。)



ShouldSerialize {}属性名()方法在支持的在Windows属性窗体控件:定义默认值与ShouldSerialize和reset方法的。正如你所看到的文件是在Windows窗体MSDN的部分不是的XmlSerializer 部分,所以,事实上,半隐藏的功能。我不知道为什么这种方法和指定属性的XmlSerializer 都存在支持。 ShouldSerialize 中的。净1.1 和我的认为的那个的minOccurs绑定支持在的。净2.0 ,所以也许早期的功能并没有完全满足XSD.EXE发展的需要(或味道)团队?



由于它是一种方法不是一个属性,它缺乏的陷阱的 {propertyName的}指定模式。这也似乎是在实践中更受欢迎,并已通过其他串行器包括:





因此,使用哪种模式呢?




  1. 如果XSD.EXE生成一个 {} propertyName的指定属性您自动,或者你的类型需要跟踪特定元素是否出现或没有在XML文件中,使用这种模式,并提防陷阱。


  2. 否则,使用 ShouldSerialize {}属性名()模式。它具有较少的陷阱和可能得到更广泛的支持。



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?

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

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.

EDIT: 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);
}

解决方案

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:

  • The <element> element is involved.
  • minOccurs is zero.
  • The maxOccurs attribute dictates a single instance.
  • The data type converts to a value type.

In this case, xsd.exe 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. If the element is encountered, {propertyName}Specified is set to true, otherwise false. Thus the deserialized instance can determine whether the property was unset, or explicitly set to its default value, during deserialization.

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

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

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.

(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.)

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?

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:

So, which pattern to use?

  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, use this pattern and watch out for the "gotchas".

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

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

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