いくつかのプロパティを持つオブジェクトを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プロパティを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 Serializerのいくつかの問題を修正します。
この属性には異なる属性があることに注意してください。
[DataContract]
public class X
{
[DataMember]
public Guid Id { get; private set; }
}
NetDataContractSerializer serializer = new NetDataContractSerializer();
TextWriter tw = new StreamWriter(_location);
serializer.Serialize(tw, obj);
編集:
Marcのコメントに基づいて更新します。クリーンなXMLを取得するには、おそらくSystem.Runtime.Serialization.DataContractSerializer
を使用する必要があります。残りのコードは同じです。
読み取り専用フィールドはXmlSerializer
を使用してシリアル化されません。これはreadonly
キーワードの性質によるものです
MSDNから:
readonlyキーワードは、フィールドで使用できる修飾子です。フィールド宣言に読み取り専用修飾子が含まれる場合、宣言によって導入されたフィールドへの割り当ては、宣言の一部として、または同じクラスのコンストラクターでのみ発生します。
だから...あなたはほとんどデフォルトのコンストラクタでフィールド値を設定する必要があります...
その特定のシリアル化モードでは不可能です(回避策については他のコメントを参照してください)。シリアライゼーションモードをそのままにする場合は、このフレームワークの制限を回避する必要があります。こちらをご覧ください 例
本質的に、プロパティpublic
をマークしますが、逆シリアル化以外のときにアクセスされた場合は例外をスローします。