XMLシリアライズできないケースに対応する。循環参照に対応する。

アトリビュートを付与しているインスタンスであればシリアライズできるが、インスタンスによっては失敗するケースがある。

■循環参照


System.InvalidOperationException はハンドルされませんでした。
Message="XML ドキュメントを生成中にエラーが発生しました。"
オブジェクトのシリアル化を実行中に循環参照が見つかりました。

上記のようなエラーは、シリアライズを行うインスタンスに循環参照が存在するためだ。具体的には次のようなインスタンスシリアライズに失敗する。


_
Public Class TreeItem
Public Name As String
Public ParentItem As TreeItem
Public Childs As New List(Of TreeItem)
End Class

TreeItemは、ChildsコレクションによってTreeItemを所有する階層構成を持つ一般的なクラスだが、ParentItemプロパティによって親階層への参照を保持している。
これが循環参照を引き起こしている。

循環参照は実データではなく参照データなので、シリアライズ対象とするのに適さない。
アトリビュートを設定することで、シリアライズ対象から外すことができる。


_
Public ParentItem As TreeItem


Imports System.IO
Imports System.Runtime.Serialization
Imports System.Xml.Serialization

_
Public Class TreeItem
Public Name As String
_
Public ParentItem As TreeItem
Public Childs As New List(Of TreeItem)
End Class

Public Class Form1

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

Dim item As New TreeItem

item.Name = "root"

Dim child As New TreeItem

child.Name = "child"
child.ParentItem = item

item.Childs.Add(child)

Dim child2 As New TreeItem

child2.Name = "aaaa"

child.Childs.Add(child2)


Dim serializer As New XmlSerializer(GetType(TreeItem))

Dim sw As New StreamWriter("c:\xml.txt")

serializer.Serialize(sw, item)

sw.Close()

End Sub

End Class


root


child


aaaa






シリアライズ・デシリアライズで循環参照を取り扱いたいなら、シリアライズ以外の方法で対処する必要がある。例えば、オブジェクトごとにシーケンスIDを付与してIDからオブジェクトを再起呼び出しで検索するようなメソッドを作る方法がその一つだ。