Ответ 1
Цель шаблона {propertyName}Specified
описана в Поддержка привязки XML-схемы: поддержка привязки атрибутов MinOccurs. Он был добавлен для поддержки элемента схемы XSD, в котором:
- Используется элемент
<element>
. - minOccurs равен нулю.
- Атрибут maxOccurs задает один экземпляр.
- Тип данных преобразуется в тип значения.
В этом случае xsd.exe /classes
будет автоматически генерировать (или вы можете вручную генерировать) свойство с тем же именем, что и элемент схемы, и a {propertyName}Specified
boolean get/set свойство, которое отслеживает, был ли элемент встречен в XML, и должен быть сериализован обратно в XML. Если элемент встречается, {propertyName}Specified
устанавливается на true
, в противном случае false
. Таким образом, десериализованный экземпляр может определить, было ли свойство отменено или явно установлено его значение по умолчанию во время десериализации.
Обратный также реализуется для генерации схемы. Если вы определяете тип С# с парой свойств, соответствующих шаблону выше, используйте 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
не связывается с нулевым значением в этом случае? Возможно, потому что:
- Нулевые атрибуты используются вместо
xsi:nil="true"
. См. Xsi: nil Поддержка привязки атрибутов. - Nullables не были представлены до .Net 2.0, так что, возможно, было поздно использовать их для этой цели?
Вам нужно знать этот шаблон, потому что xsd.exe
иногда генерирует его для вас автоматически, однако взаимодействие между свойством и свойством Specified
является странным и способным создавать ошибки. Вы можете заполнить все свойства в своем классе, а затем сериализовать XML и потерять все, потому что вы также не установили соответствующие свойства Specified
на true
. Эта "гоча" появляется здесь время от времени здесь, см., Например, этот вопрос или этот тоже.
Еще одна "полученная" с этим шаблоном заключается в том, что если вам нужно сериализовать свой тип с помощью сериализатора, который не поддерживает этот шаблон, вы можете > вручную отключить вывод этого свойства во время сериализации, и , вероятно, будет необходимо вручную установить его во время десериализации. Поскольку каждый сериализатор может иметь свой собственный собственный механизм для подавления свойств (или вообще никакого механизма!), Это может стать все более обременительным с течением времени.
(Наконец, я немного удивлен, что ваш MyPropertySpecified
работает успешно без сеттера. Кажется, я вспоминаю версию .Net 2.0, в которой отсутствующий установщик {propertyName}Specified
может вызвать исключение. он больше не воспроизводится в более поздних версиях, и у меня нет 2.0 для тестирования. Так что это может быть третий вопрос.)
Поддержка метода ShouldSerialize{PropertyName}()
задокументирована в Свойствах в элементах управления Windows Forms: определение значений по умолчанию с помощью методов ShouldSerialize и Reset. Как видите, документация находится в разделе Windows Forms в MSDN, а не в разделе XmlSerializer
, так что это, по сути, полузакрытая функциональность. Я не знаю, почему поддержка этого метода и свойство Specified
существуют в XmlSerializer
. ShouldSerialize
был введен в .NET 1.1, и я считаю, что поддержка привязки MinOccurs была добавлена в .NET 2.0, поэтому, возможно, более ранняя функциональность не вполне соответствовала потребностям (или вкусу) команды разработчиков xsd.exe
?
Поскольку это метод, а не свойство, ему не хватает "gotchas" шаблона {propertyName}Specified
. Он также кажется более популярным на практике и был принят другими сериализаторами, включая:
- Json.NET
- protobuf-net (который утверждает, что поддерживает оба шаблона.)
Итак, какой шаблон использовать?
-
Если
xsd.exe
автоматически генерирует свойство{propertyName}Specified
, или ваш тип должен отслеживать, появился или нет какой-либо конкретный элемент в XML файле, или вам нужен автогенератор XSD, чтобы указать, что определенное значение является необязательным, используйте этот шаблон и следите за "gotchas". -
В противном случае используйте шаблон
ShouldSerialize{PropertyName}()
. Он имеет меньше ошибок и может быть более широко поддержан.