序列化私有成员数据

我试图将一个对象序列化为具有许多属性的 XML,其中一些属性是只读的。

public Guid Id { get; private set; }

我已经标记了类[ Serializer ] ,并且实现了 ISerializer 接口。

下面是我用来序列化对象的代码。

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

不幸的是,它在第一行与此消息失败。

未处理 InvalidOperationException: 无法生成临时类(result = 1)。 Error CS0200: 属性或索引器“ MyObject.Id”无法分配给——它是只读的

如果我将 Id 属性设置为 public,它就可以正常工作。谁能告诉我,我是否在做什么,或者至少是否有可能做什么?

70203 次浏览

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.

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.

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...

Its not possible with that particular serialization mode (see the other comments for workarounds). If you really want to leave your serialization mode as-is, you have to work around the framework limitations on this one. See this example

Esentially, mark the property public, but throw an exception if it's accessed at any time other than deserialization.