Pergunta

Eu estou tentando serializar um objeto para XML que tem um número de propriedades, alguns dos quais são somente leitura.

public Guid Id { get; private set; }

Eu marquei a classe [Serializable] e eu implementei a interface ISerializable.

Abaixo está o código que estou usando para serializar meu objeto.

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

Infelizmente ele cai na primeira linha com esta mensagem.

InvalidOperationException was unhandled: Não é possível gerar uma classe temporária (resultado = 1). CS0200 de erro: Propriedade ou indexador 'MyObject.Id' não pode ser atribuído a - é somente leitura

Se eu definir a propriedade ID para público funciona bem. Alguém pode me dizer se eu estou fazendo algo, ou pelo menos se o seu mesmo possível?

Foi útil?

Solução

Você pode usar DataContractSerializer (mas note que você não pode usar atributos xml - únicos elementos 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);
        }
    }
}

Como alternativa, você pode implementar IXmlSerializable e fazer tudo sozinho - mas isso funciona com XmlSerializer, pelo menos

.

Outras dicas

Você pode usar o System.Runtime.Serialization.NetDataContractSerializer. É mais poderoso e corrige alguns problemas do clássico Serializer XML.

Note que existem diferentes atributos para este.

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


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

Editar:

Atualização com base no comentário de Marc: Você provavelmente deve usar System.Runtime.Serialization.DataContractSerializer para o seu caso para obter uma XML limpo. O resto do código é o mesmo.

Somente leitura campos não será serializado usando o XmlSerializer, isso é devido à natureza do readonly palavra-chave

De MSDN:

O somente leitura palavra-chave é um modificador que você pode usar nos campos. Quando uma declaração de campo inclui um readonly modificador, atribuições para os campos introduzidas pela declaração só pode ocorrer como parte da declaração ou em um construtor na mesma classe.

Então ... você faria praticamente necessidade de definir o valor de campos no padrão construtor ...

A sua não é possível com esse modo particular de serialização (ver os outros comentários para soluções alternativas). Se você realmente quiser deixar o seu modo de serialização como está, você tem que contornar as limitações estruturais em um presente. Veja este exemplo

esentially, marcar o public propriedade, mas lançar uma exceção se ele é acessado a qualquer momento que não seja a desserialização.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top