2009-04-29 7 views
71

私はいくつかのプロパティを持つ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プロパティを設定した場合、それが唯一の

読み込まれます。誰かが私が何かをしているか、少なくともそれが可能であれば教えてもらえますか?

答えて

57

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と連携し、少なくとも、 。

+0

+1、私の答えに関する助言をいただきありがとうございます。 –

+0

DataContractSerializerを使用するようにコードを変更しましたが、GetObjectDataメソッドがまだ実行されていることがわかりました。私は自分のプロパティに属性を入れてシリアル化するか、ISerializableインターフェイスを実装できると思っていますか? –

+0

ISerializable(またはIXmlSeializable?)を実装している場合は、基本的にはすべて自分で作業しています... –

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); 

編集:マルクさんのコメントに基づいて

更新:あなたはおそらく、きれいなXMLを取得するために、あなたのケースのためのSystem.Runtime.Serialization.DataContractSerializerを使用する必要があります。残りのコードは同じです。

あなたが DataContractSerializer(しかし、あなたは、XML属性を使用することはできません - 唯一のXML要素)を使用することができ
+0

NetDataContractSerializerはxml ...を記述しません。むしろ、外部消費に適したクリーンxmlではありません。その中にアセンブリメタデータがあります。 –

+0

@Marc:ヒントのためにありがとう。それは常に達成したいものに依存します。 DataContractSerializerはおそらくここで期待されるものです。 –

1

読むだけのフィールドはXmlSerializerを使用して直列化されることはありません、これが原因MSDNからreadonlyキーワード

の性質のためにされています

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

だから...あなたはかなりその特定のシリアル化モードでデフォルトコンストラクタ内のフィールド値...

+0

私はISerializable.GetObjectDataメソッドを実装していたので、XmlSerializerはそれを使ってシリアル化したい情報を取得し、読み込み専用のプロパティにアクセスしないと思った。 –

+0

XmlSerializerはISerializableを気にしません - IXmlSerializableのみ –

+0

Marcありがとうございます。 –

0

そのことはできませんを設定する(回避策のための他のコメントを参照)する必要があります。シリアル化モードをそのままの状態にしたい場合は、このフレームワークの制限事項を回避する必要があります。これを参照してくださいexample

具体的には、プロパティpublicをマークしますが、デシリアライズ以外のときにアクセスされた場合は例外をスローします。

+5

"例外をスローする" - XmlSerializerはシリアライゼーションコールバックをサポートしていないので、あなたは知る方法がありません... –

+1

'System.Diagnostics.StackTrace'を使用して、あなたのプロパティを呼び出すものを見つけることができますそのようなソリューションをお勧めします:-) –