Почему свойства без сеттера не сериализуются

101

У меня есть сериализуемый класс, и одно из свойств в моем классе генерирует Guidв получателе. Свойство не реализует сеттер и игнорируется во время сериализации. Почему это так, и всегда ли мне нужно реализовать сеттер, чтобы мое свойство было сериализовано.

[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-Serializable нужен конструктор без параметров ».


Кроме того, IXmlSerializable

В дополнение к указанным выше типам, которые могут быть сериализованы с помощью сериализатора XML, любой тип, реализующий интерфейс IXmlSerializable, может быть сериализован и десериализован. В частности, это означает, что типы XElement и XDocument могут быть сериализованы.

См. « Интерфейс IXmlSerializable ».

Джон Сондерс
источник
6

Ограничение XMLSerializer- свойства без сеттера не могут быть сериализованы.

Но вы можете использовать DataContractSerializerдля сериализации private setter properties-

[DataMember]
public string Id
{
    get
    {
         return Guid.NewGuid().ToString();
    }
    private set {}
}
Рохит Чаны
источник
1
Свойство должно быть сериализовано как xml-атрибут (см. Исходный пост). Ваш код (атрибут DataMember) создает xml-элемент. Насколько я знаю, не существует (чистого) способа сообщить DataContractSerializer о необходимости преобразования свойства в атрибут, а не в элемент. DataContractSerializer удобен, но вы всегда должны помнить об этом ограничении.
sth_Weird
2

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

Edamon
источник
0

Атрибуты сериализации используются для сериализации и десериализации объектов. XmlSerializer предполагает, что вам не нужно сериализовать какое-либо свойство, у которого нет установщика. Установщик будет использоваться при десериализации строки в объект, потому что необходимо создать экземпляр объекта, а затем установщик будет использоваться для заполнения значения свойства.

Руи Джаримба
источник