Недокументированный способ сохранить свойство для сериализации в XML [duplicate]

аргумент VM работал для меня в eclipse. Если вы используете eclipse версии 3.4, выполните следующие

, перейдите к Run --> Run Configurations -->, затем выберите проект в разделе maven build ->, затем выберите вкладку «JRE» ->, затем введите -Xmx1024m.

В качестве альтернативы вы можете сделать Run --> Run Configurations --> select the "JRE" tab -->, а затем ввести - Xmx1024m

Это должно увеличить кучу памяти для всех сборок / проектов. Вышеуказанный размер памяти составляет 1 ГБ. Вы можете оптимизировать то, что хотите.

15
задан JNYRanger 15 June 2016 в 15:38
поделиться

2 ответа

Цель шаблона {propertyName}Specified описана в Поддержка привязки XML-схемы: поддержка привязки атрибутов MinOccurs . Он был добавлен для поддержки элемента схемы XSD, в котором:

  • Используется элемент <element>.
  • minOccurs равен нулю.
  • MaxOccurs атрибут задает один экземпляр.
  • Тип данных преобразуется в тип значения.

В этом случае xsd.exe /classes автоматически сгенерирует (или вы можете вручную создать) свойство с тем же именем, что и элемент схемы, и {propertyName}Specified boolean get / set property , который отслеживает, был ли элемент встречен в 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 не связывается с Nullable<T> в этом случае? Возможно, потому что:

Вам нужно знать этот шаблон, потому что 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 и I считают , что поддержка привязки MinOccurs была добавлена ​​в .Net 2.0 , поэтому, возможно, более ранние функции didn 't вполне удовлетворяет потребности (или вкуса) команды разработчиков xsd.exe?

Поскольку это метод не является свойством, ему не хватает «gotchas» шаблона {propertyName}Specified. Он также кажется более популярным на практике и был принят другими сериализаторами, включая:

Итак, какой шаблон использовать?

  1. Если xsd.exe автоматически генерирует свойство {propertyName}Specified, или ваш тип должен отслеживать, появился или нет конкретный элемент в файле XML, или вам нужен автогенератор XSD чтобы указать, что определенное значение является необязательным, используйте этот шаблон и следите за «gotchas».
  2. В противном случае используйте шаблон ShouldSerialize{PropertyName}(). Он имеет меньше ошибок и может быть более широко поддержан.
21
ответ дан NH. 20 August 2018 в 06:55
поделиться

Чтобы добавить к очень подробному ответу @dbc, я столкнулся с проблемой управления сериализацией в производных классах. В моей ситуации у меня был базовый класс и производный класс, в котором свойство Prop было переопределено.

public class BaseClass
{
    public virtual string Prop {get; set;}
}

public class Derived: BaseClass
{
    public string Comp1 {get; set;}
    public string Comp2 {get; set;}
    public override string Prop {get => Comp1 + Comp2; set {}}
}

Поскольку вычисляется свойство Prop в производном классе, для класса Derived Я хотел сериализовать Comp1 и Comp2, но не Prop. Оказывается, установка атрибута XmlIgnore в свойстве Prop в классе Derived не работает, а Prop сериализована.

Я также попытался добавить метод ShouldSerializeProp и свойство PropSpecified в классе Derived, но не работает. Я попытался установить точки останова, чтобы узнать, вызваны ли они, а они нет.

Оказывается, что XmlSerializer смотрит на исходный класс, где свойство Prop впервые появляется в иерархии классов, чтобы решить, сериализовать свойство или нет. Чтобы иметь возможность управлять сериализацией в производном классе, сначала мне пришлось добавить virtual ShouldSerializeProp в класс Base.

public class Base
{
    .....
    public virtual bool ShouldSerializeProp() {return true;}
}

Тогда я мог бы переопределить ShouldSerializeProp в классе Derived и вернуть false.

public class Derived: Base
{
    .....
    public override bool ShouldSerializeProp() {return false;}
}

Этот шаблон позволяет различным производным классам выбирать, какие свойства из родительский класс они сериализуются. Надеюсь это поможет.

2
ответ дан Tibi 20 August 2018 в 06:55
поделиться
  • 1
    Отличная точка @ Тиби. Я задал этот вопрос несколько лет назад, но то, что я узнал с тех пор, всегда должно делать такие классы сериализации как запечатанные, если вы заранее не знаете, что будут производные классы из-за необходимости использования виртуальных методов. – JNYRanger 10 January 2018 в 15:50
Другие вопросы по тегам:

Похожие вопросы: