Чому властивості без сетера не серіалізуються


101

У мене є серіалізаційний клас, і одна з властивостей мого класу генерує a Guidв getter. Властивість не реалізує сеттер і ігнорується під час серіалізації. Чому це і чи потрібно мені завжди реалізовувати сетер для того, щоб моє майно було серіалізоване.

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
    }
}

Я спробував реалізувати порожній сетер, і він правильно серіалізувався.

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
        set {}
    }
}

Оновлення :

Чи можете ви вказати, як я повинен визначати властивості, значення яких ніколи не змінюються, або ті, для яких значення генерується внутрішньо?


1
Другий приклад правильно серіалізувати ... Але що станеться, коли ви намагаєтесь його десаріалізувати?
LightStriker

Спробуйте YAXLib [+ , + ]
Сина Іраванян

3
FYI, XML-серіалізатор ігнорує [Serializable].
Джон Сондерс

@JohnSaunders Я про це не знав.
Костянтин Дінев

Відповіді:


60

Це обмеження, XmlSerializerоскільки воно не серіалізує властивості лише для читання, те, що ви зробили у своєму другому прикладі - це, по суті, хак, щоб змусити його серіалізувати, однак, марно, якщо вам потрібно це деаріалізувати пізніше.

Крім того, ви можете перейти на використання DataContractSerializer , він більш гнучкий.


8
DataContractSerializer також вимагає сетерів. Це обмеження, оскільки хоч ми можемо використовувати його лише для одного типу операцій, скажімо, десеріалізації, але декларації повинні бути обома інакше, процес серіалізації не знатиме, що робити зі значенням, коли він намагається серіалізувати XML в об’єкти.
ryadavilli

7
@ryadavilli все, що позначено як [DataMember], серіалізується за допомогою DataContractSerializer(лише для читання чи ні).
Джеймс

1
@James Я написав вище, тому що у мене виникли деякі помилки часу компіляції, коли я спробував те саме. Тепер, коли я повернувся до свого коду та видалив сетер, він, здається, склався нормально. Це дуже сміливо і, напевно, для мене домашнє завдання, щоб дізнатися більше про це.
ryadavilli

3
Нарешті, знайшов джерело моєї плутанини. Встановник властивості не потрібен для серіалізації. Однак, якщо у властивості немає сеттера, XML не десеріалізується до об'єкта. Там домашнє завдання закінчено.
ryadavilli

1
@ryadavilli так, це просто обмеження в XmlSerializerреалізації, воно покладається на метод публічного налаштування. DataContractSerializerв цьому сенсі трохи розумніший (можливо, використовуючи роздуми для встановлення поля за лаштунками).
Джеймс

10

Див. " Представлення XML-серіалізації " в документації MSDN. Серед іншого, в ньому сказано:

Предмети, які можна серіалізувати

Наступні елементи можна серіалізувати за допомогою класу XmlSerializer:

Public read/write properties and fields of public classes.

Classes that implement ICollection or IEnumerable.

Примітка:

Only collections are serialized, not public properties.
XmlElement objects.

XmlNode objects.

DataSet objects.

Також дивіться " Чому для XML-серіалізаційного класу потрібен конструктор без параметрів "


Також IXmlSerializable

На додаток до перерахованих вище типів, які можна серіалізувати за допомогою XML-серіалізатора, будь-який тип, який реалізує інтерфейс IXmlSerializable, може бути серіалізований та десеріалізований. Зокрема, це означає, що типи XElement та XDocument можна серіалізувати.

Див. Розділ " IXmlSerializable Interface ".


6

Обмеження XMLSerializer- Не можна серіалізувати властивості без налаштування.

Але ви можете використовувати DataContractSerializerдля серіалізації private setter properties-

[DataMember]
public string Id
{
    get
    {
         return Guid.NewGuid().ToString();
    }
    private set {}
}

Властивість повинна бути серіалізована як атрибут xml (див. Оригінальну публікацію). Ваш код (атрибут DataMember) створює xml-елемент. Наскільки я знаю, немає (чистого) способу сказати DataContractSerializer, щоб перетворити властивість в атрибут, а не в елемент. DataContractSerializer є приємним, але ви завжди повинні пам’ятати про це обмеження.
sth_Weird

2

якщо ви хочете мати приватні сетери, а об’єкт бути серіалізаційним / десяриалізаційним, імпліментованим ISerializable та створити конструктор на зразок MyObject (інформація про SerializationInfo, контекст StreamingContext). Приклад можна знайти тут .


0

Атрибути серіалізації використовуються для серіалізації та десеріалізації об'єктів. XmlSerializer припускає, що вам не потрібно серіалізувати будь-яке властивість, у якій немає сеттера. Setter буде використовуватися при десеріалізації рядка в об'єкт, тому що потрібно створити екземпляр об'єкта, а потім сеттер використовуватиметься для заповнення значення властивості.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.