75

オブジェクトを XML にシリアル化しようとしています。この 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 に設定すると、正常に動作します。私が何かをしているかどうか、または少なくともそれが可能であるかどうかを誰かに教えてもらえますか?

4

4 に答える 4

64

使用できます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は少なくとも で機能します。

于 2009-04-29T14:57:00.520 に答える
6

を使用できますSystem.Runtime.Serialization.NetDataContractSerializer。より強力になり、従来の Xml シリアライザーのいくつかの問題が修正されました。

これには異なる属性があることに注意してください。

[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 のコメントに基づく更新:System.Runtime.Serialization.DataContractSerializerきれいな XML を取得するには、おそらく for your case を使用する必要があります。コードの残りの部分は同じです。

于 2009-04-29T14:51:53.997 に答える
2

読み取り専用フィールドは、 を使用してシリアル化されません。これは、キーワードXmlSerializerの性質によるものです。readonly

MSDN から:

readonlyキーワードは、フィールドで使用できる修飾子です。フィールド宣言に readonly 修飾子が含まれている場合、宣言によって導入されたフィールドへの割り当ては、宣言の一部として、または同じクラスのコンストラクターでのみ発生できます。

したがって...デフォルトのコンストラクターでフィールド値を設定する必要があります...

于 2009-04-29T14:59:45.630 に答える
0

その特定のシリアル化モードでは不可能です (回避策については、他のコメントを参照してください)。シリアライゼーション モードをそのままにしたい場合は、このフレームワークの制限を回避する必要があります。この例を参照してください

基本的に、プロパティをマークしますpublicが、逆シリアル化以外のときにアクセスされた場合は例外をスローします。

于 2009-04-29T15:14:15.267 に答える