Сериализация личных данных члена - PullRequest
73 голосов
/ 29 апреля 2009

Я пытаюсь сериализовать объект в 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, оно будет работать нормально. Может кто-нибудь сказать мне, если я что-то делаю, или, по крайней мере, если это вообще возможно?

Ответы [ 4 ]

60 голосов
/ 29 апреля 2009

Вы можете использовать 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, по крайней мере.

6 голосов
/ 29 апреля 2009

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

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

[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:

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

2 голосов
/ 29 апреля 2009

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

Из MSDN:

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

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

0 голосов
/ 29 апреля 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...