Serializing private member data
I'm trying to serialize an object to XML that has a number of properties, some of which are readonly.
public Guid Id { get; private set; }
I have marked the class [Serializable] and I have implemented the ISerializable interface.
Below is the code I'm using to serialize my object.
public void SaveMyObject(MyObject obj)
{
XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
TextWriter tw = new StreamWriter(_location);
serializer.Serialize(tw, obj);
tw.Close();
}
Unfortunately it falls over on the first line with this message.
InvalidOperationException was unhandled: Unable to generate a temporary class (result=1). error CS0200: Property or indexer 'MyObject.Id' cannot be assigned to -- it is read only
If I set the Id property to public it works fine. Can someone tell me if I'm doing something, or at least if its even possible?
Solution 1:
You could use DataContractSerializer
(but note you can't use xml attributes - only xml elements):
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);
}
}
}
Alternatively, you can implement IXmlSerializable
and do everything yourself - but this works with XmlSerializer
, at least.
Solution 2:
You could use the System.Runtime.Serialization.NetDataContractSerializer
. It is more powerful and fixes some issues of the classic Xml Serializer.
Note that there are different attributes for this one.
[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:
Update based on Marc's comment: You should probably use System.Runtime.Serialization.DataContractSerializer
for your case to get a clean XML. The rest of the code is the same.
Solution 3:
Read only fields will not be serialized using the XmlSerializer
, this is due to the nature of the readonly
keyword
From MSDN:
The readonly keyword is a modifier that you can use on fields. When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.
So... you would pretty much need to set the fields value in the default constructor...