Сериализация личных данных участника
-
03-07-2019 - |
Вопрос
Я пытаюсь сериализовать объект в 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 значение public, оно будет работать нормально.Может ли кто-нибудь сказать мне, делаю ли я что-то, или, по крайней мере, возможно ли это вообще?
Решение
Вы могли бы использовать 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
, по крайней мере.
Другие советы
Вы могли бы использовать 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);
Редактировать:
Обновление, основанное на комментарии Марка:Вероятно, вам следует использовать System.Runtime.Serialization.DataContractSerializer
для вашего случая необходимо получить чистый XML-файл.Остальная часть кода такая же.
Поля, доступные только для чтения, не будут сериализованы с помощью XmlSerializer
, это связано с характером readonly
ключевое слово
Из MSDN:
Тот Самый только для чтения ключевое слово - это модификатор, который вы можете использовать для полей.Когда объявление поля включает модификатор только для чтения, присвоения полям, введенным объявлением, могут выполняться только как часть объявления или в конструкторе того же класса.
Итак...вам в значительной степени нужно было бы установить значение полей в конструкторе по умолчанию...
Это невозможно с этим конкретным режимом сериализации (смотрите Другие комментарии для обходных путей).Если вы действительно хотите оставить свой режим сериализации как есть, вам придется обойти ограничения фреймворка в этом случае.Видишь это пример
По сути, отметьте свойство public
, но генерирует исключение, если к нему обращаются в любое время, отличное от десериализации.