- PR -

private なListオブジェクトの中のオブジェクトもシリアライズしたい

1
投稿者投稿内容
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2007-06-22 09:38
こんにちは。お世話になってます。

たとえば、以下のようなソースコードがあります。
Formのコマンドボタンを押すと、ClassDオブジェクトを生成してシリアライズしてxmlファイルを出力します。
ClassDにClassEを保持するList型の変数がありますが、List型の変数そのものはprivateにしており、property経由のみでアクセスするようにしています。

この際、ClassEに保持しているClassAを保持するList型の中のオブジェクトもシリアライズ/デシリアライズしたいのですが、xmlに出力されません。

これらもxmlに出力したいのですが、どうすればいいのでしょうか?
やはり、xmlに吐き出したい変数はprivateとpropertyにせず、publicにすべきですか?

以下のソースは説明しやすいように、VB.NET 2005 で書いていますが、実際の開発はVC++.NET 2005 C++/CLI でやってます。

コード:



Public Class ClassA
Public a As Integer
Public b As Integer

End Class

Public Class ClassB
Inherits ClassA
Public c As Integer

End Class

Public Class ClassC
Inherits ClassA
Public c As Double

End Class


Imports System.Xml.Serialization
Public Class ClassD
Private m_a As New ClassE
Public b As Integer

<XmlArrayItem(GetType(ClassE))> _
ReadOnly Property a() As ClassE
Get
Return m_a
End Get
End Property

End Class

Imports System.Xml.Serialization
Public Class ClassE
Public m_a As New List(Of ClassA)

<XmlArrayItem(GetType(ClassB)), XmlArrayItem(GetType(ClassC))> _
ReadOnly Property a() As List(Of ClassA)
Get
Return m_a
End Get
End Property

Sub New()
m_a.Add(New ClassB)
End Sub
End Class


'Form1に Button1 が配置されている
Public Class Form1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim myClasses As New ClassD

''ArrayListに挿入できるオブジェクト型のType配列を作成
'Dim et() As Type = {GetType(SampleClass2)}

'ArrayListに挿入できるオブジェクトを指定して
'XMLファイルに保存する
Dim serializer As _
New System.Xml.Serialization.XmlSerializer( _
GetType(ClassD))
Dim fs As New System.IO.FileStream( _
"C:\test.xml", System.IO.FileMode.Create)
serializer.Serialize(fs, myClasses)
'閉じる
fs.Close()

End Sub
End Class






[ メッセージ編集済み 編集者: maru 編集日時 2007-06-22 09:40 ]
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2007-06-22 09:48
自己レスです。

http://msdn2.microsoft.com/ja-jp/library/bdxxw552(VS.80).aspx
に「オブジェクトのパブリックとプライベート両方のフィールドとプロパティをすべてシリアル化するには、BinaryFormatter を使用します。」とありました。

BinaryFormatter を調べてみます。

お騒がせしました。
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2007-06-22 11:07
あれから BinaryFormatter でシリアライズを試みています。

VB.NETで小さなサンプルプログラムをつくって検証してみて要領がわかったので、
本アプリ(VC++.NET 2005 C++/CLI)に組み込もうとしています。

関連しそうなクラスに Serializable属性 や NonSerialized属性 をつけたりして
BinaryFormatter でシリアライズしてみているのですが、「○○はシリアル化可能として設定されていません。」という旨のメッセージが出ます。

大まかなクラス図を描いて、関連するクラスを見つけては属性をつけて、実行してみての繰り返しで、少しづつつぶしているのですが、クラス構造が巨大で複雑なため結構地味な作業です。
何か簡単にできる方法はないでしょうか?





[ メッセージ編集済み 編集者: maru 編集日時 2007-06-22 11:15 ]
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-06-22 15:42

>やはり、xmlに吐き出したい変数はprivateとpropertyにせず、publicにすべきですか?

いいえ。
たとえデータを保持するだけのクラスであっても、
検証動作などを入れる可能性はあります。
propertyはpropertyのままでシリアライズするべきです。

ぱっと見たところ、
コード:
    <XmlArrayItem(GetType(ClassE))> _
    ReadOnly Property a() As ClassE
        Get
            Return m_a
        End Get
    End Property


ここは問題があります。
ReadOnlyだとプロパティaを設定できません。
コレクション以外はReadOnlyにできなかったと記憶しています。

シリアライザの中で、ClassEを作成してからClassDに設定するのを理解すれば、
ClassEに引数なしコンストラクタが必要、
ClassDの該当プロパティはReadOnlyではだめ、
というのが理解できるかと思います。

>何か簡単にできる方法はないでしょうか?

なにが大変なのか、よくわかりませんが、

クラス作成時からシリアル化を考慮し、
SerializableであろうクラスにはかならずSerializableをつけるのが
普通ですので、あまり困ったことがありません。

>何か簡単にできる方法はないでしょうか?
>クラス構造が巨大で複雑なため結構地味な作業です。

地味にやればできるとわかっているなら、それが一番簡単です。
また、プログラムは、一般的に地味な作業です。
派手にプログラムを組む人を見たことがありません。


Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-06-22 18:54
もう一回、XMLシリアライズ関係のリファレンスを読み直そう。
private なフィールドでも、public で読み書き可能なプロパティがあれば、XMLシリアライズできます。


GDNJにあるんだよな...
_________________
1

スキルアップ/キャリアアップ(JOB@IT)