質問

いくつかのプロパティを含む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が処理されませんでした:   一時クラスを生成できません(result = 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 をマークしますが、逆シリアル化以外のときにアクセスされた場合は例外をスローします。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top