Сериализация данных частного участника

Я пытаюсь сериализовать объект в XML, который имеет ряд свойств, некоторые из которых доступны только для чтения.

public Guid Id { get; private set; }

Я отметил класс [Serializable], и ​​я реализовал интерфейс ISerializable.

Ниже приведен код, который я использую для сериализации моего объекта.

public void SaveMyObject(MyObject obj)
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
    TextWriter tw = new StreamWriter(_location);
    serializer.Serialize(tw, obj);
    tw.Close();
}

К сожалению, он падает на первую строку с этим сообщением.

Ошибка InvalidOperationException была необработанной: Не удалось создать временный класс (результат = 1). ошибка CS0200: свойство или индекс "MyObject.Id" не может быть назначено - это только чтение

Если я устанавливаю свойство Id публично, он отлично работает. Может кто-нибудь сказать мне, если я что-то делаю, или, по крайней мере, если это возможно?

Ответ 1

Вы можете использовать DataContractSerializer (но обратите внимание, что вы не можете использовать атрибуты xml - только элементы xml):

using System;
using System.Runtime.Serialization;
using System.Xml;
[DataContract]
class MyObject {
    public MyObject(Guid id) { this.id = id; }
    [DataMember(Name="Id")]
    private Guid id;
    public Guid Id { get {return id;}}
}
static class Program {
    static void Main() {
        var ser = new DataContractSerializer(typeof(MyObject));
        var obj = new MyObject(Guid.NewGuid());
        using(XmlWriter xw = XmlWriter.Create(Console.Out)) {
            ser.WriteObject(xw, obj);
        }
    }
}

В качестве альтернативы вы можете реализовать IXmlSerializable и сделать все сами, но это работает с XmlSerializer, по крайней мере.

Ответ 2

Вы можете использовать System.Runtime.Serialization.NetDataContractSerializer. Он более мощный и исправляет некоторые проблемы классического Xml Serializer.

Обратите внимание, что для этого есть разные атрибуты.

[DataContract]
public class X
{
  [DataMember]
  public Guid Id { get; private set; }
}


NetDataContractSerializer serializer = new NetDataContractSerializer();
TextWriter tw = new StreamWriter(_location);
serializer.Serialize(tw, obj);

Edit:

Обновление, основанное на комментарии Marc: Вероятно, вы должны использовать System.Runtime.Serialization.DataContractSerializer для вашего случая, чтобы получить чистый XML. Остальная часть кода одинаков.

Ответ 3

Только поля чтения не будут сериализованы с использованием XmlSerializer, это связано с характером ключевого слова readonly

Из MSDN:

Ключевое слово readonly - это модификатор, который можно использовать для полей. Когда объявление поля включает модификатор readonly, присваивания полям, введенным декларацией, могут возникать только как часть объявления или в конструкторе того же класса.

Итак... вам бы очень нужно было установить значение полей в конструкторе по умолчанию...

Ответ 4

Это невозможно в этом режиме сериализации (см. другие комментарии для обходных решений). Если вы действительно хотите оставить свой режим сериализации как есть, вам придется обойти ограничения фреймворка на этом. Смотрите пример

Как правило, отметьте свойство public, но создайте исключение, если оно будет доступно в любое время, кроме десериализации.