PowerTools SPREAD for Windows Forms 8.0J > 開発者ガイド > ファイル入出力 > シリアル化 > Serializer クラスの実装 |
Serializerクラスを使用する場合、以下の点に注意してください。
後述のサンプルコードでは、整数値や色など単純なデータを保存する方法を示していますが、他のタイプのデータを保存する場合も、同様です。Serializerクラスには、Color、DateTime、DateTimeFormatInfo、Enum型、Font、Image、Int32配列、NumberFormatInfo、PointF配列、String配列、およびObjectを、それぞれ保存および読み込むためのメソッドが存在します。可能な限り限定的なメソッドを使用することをお勧めします。たとえば、単純型やColor値の保存にSerializeObjectメソッドを使用することもできますが、効率的ではなく、同一のXMLを復元できない場合もあります。
特定の型に対して作成されたメソッドには、概して理由があります。DateTimeFormatInfoおよびNumberFormatInfoオブジェクトは、それぞれ固有のメソッドを使用して保存する必要があります。SerializeObjectメソッドでは、既定でバイナリ型のシリアル化が使用されますが、この方法では、フレームワークのバージョンが異なると正しく機能しません。たとえば、.NET 1.0を使用して保存されたDateTimeFormatInfoは、.NET 1.1または2.0を使用して読み込むことができません。
Int32、String、Boolean などの単純型の場合は、単純に ToString() を使用して文字列に変換してから保存し(可能な場合、CultureInfoクラスのInvariantCultureプロパティの値を指定して)、XmlConvertクラスを使用して文字列を値に戻す方法が最適です。
SaveObjectメソッドは、ISerializeSupportインタフェースを実装するオブジェクト、特定の型(組み込みのデータ型およびDataSetオブジェクト)、およびシリアル化が可能ではあるもののISerializeSupportインタフェースを実装していないオブジェクトの保存を目的としています。このようなオブジェクトは、EncodeObjectメソッドを使用して保存されます。EncodeObjectメソッドは、BinaryFormatterクラスを使用してオブジェクトをMemoryStreamオブジェクトに保存してから、Convertクラスを使用してBase64文字列にエンコードします。
デバッグビルドによってファイルを保存し、厳密な名前の付いたリリースビルドとしてロードするには、オブジェクトを保存したノードでアセンブリ属性を除去または更新する必要があります。SerializeObjectメソッドは、オブジェクトの型を定義したアセンブリが、呼び出しアセンブリおよび実行アセンブリ(FarPoint.Win.dll)と異なる場合、アセンブリ属性を記述します。
呼び出しアセンブリは、通常、FarPoint.Win.Spread.dllです。しかし、開発者がISerializeSupportインタフェースを実装する独自のオブジェクトを定義し、SerializeObjectメソッドを使用して子オブジェクトを保存している場合、開発者のアセンブリとなる場合があります。注意が必要な例として、開発者が、製品のオブジェクトモデルに組み込むカスタムオブジェクト(たとえば、独自のデータモデル)を作成した場合に、コントロールの保存と読み込みにはFpSpreadクラスの保存および読み込みメソッドを使用し、作成したアセンブリの異なるビルドを使用しようとする状況が考えられます。
この場合、オブジェクトの型定義を含む適切なアセンブリを読み込むために、アセンブリ属性が必要ですが、デバッグビルドとリリースビルドでは正しい属性が異なります。このような場合、XML内の値を編集して、アセンブリ参照を変更する必要があります(StringクラスのReplaceメソッドなどを使用)。
稀なケースでは、ISerializeSupportインタフェース、およびSerializerクラスを使用して、独自に定義したオブジェクトを含むファイルを保存および読み込む場合にも注意が必要です。このようなオブジェクトは、同一アセンブリ内に含まれることも、並行して記述している別のアセンブリに含まれることもあります。各オブジェクトが同一アセンブリ内で定義されている場合、アセンブリ属性は出力されません。異なるアセンブリで定義されている場合、callingAssembly引数を受け取るSerializeObject、およびCreateObjectInstanceAndDeserializeメソッドのオーバーロードを呼び出して、該当オブジェクトを保持するアセンブリ(Serializerクラスを呼び出したアセンブリでなくてもかまわない)を渡すことができます。これにより、アセンブリ属性が出力されなくなります。重要な点は、この処理を保存、および読み込みの呼び出しの両方で行うことです。これにより、型参照が解決され、オブジェクトのインスタンスが作成されます。
次のサンプルコードは、LineBorderクラスを例に、製品でISerializeSupportインタフェースがどのように実装されているかを示します。
C# |
コードのコピー
|
---|---|
// ISerializeSupportインタフェースの実装には、引数なしのコンストラクタが必要です。 // パブリックである必要はありません。 internal LineBorder() { color = SystemColors.WindowFrame; thickness = 1; left = top = right = bottom = true; inset = new FarPoint.Win.Inset(1); } /// <summary> /// オブジェクトを XML に保存します。 /// </summary> /// <param name="w">オブジェクトの保存先となる XmlTextWriter オブジェクトです。</param> /// <returns>成功した場合は True を、そうでない場合は False を返します。</returns> public virtual bool Serialize(System.Xml.XmlTextWriter w) { w.WriteStartElement("Inset"); w.WriteElementString("Bottom", inset.Bottom.ToString()); w.WriteElementString("Left", inset.Left.ToString()); w.WriteElementString("Right", inset.Right.ToString()); w.WriteElementString("Top", inset.Top.ToString()); w.WriteEndElement(); FarPoint.Win.Serializer.SerializeColor(color, "Color", w); w.WriteStartElement("Sides"); w.WriteElementString("Bottom", bottom.ToString()); w.WriteElementString("Left", left.ToString()); w.WriteElementString("Right", right.ToString()); w.WriteElementString("Top", top.ToString()); w.WriteEndElement(); w.WriteElementString("Thickness", thickness.ToString(System.Globalization.CultureInfo.InvariantCulture)); return true; } /// <summary> /// XML からオブジェクトをロードします。 /// </summary> /// <param name="r">オブジェクトをロードする XmlNodeReader です。</param> /// <returns>成功した場合は True を、そうでない場合は False を返します。</returns> public virtual bool Deserialize(System.Xml.XmlNodeReader r) { bool inInset = false; bool inBottom = false; bool inLeft = false; bool inRight = false; bool inTop = false; bool inColor = false; bool inSides = false; bool inThickness = false; int bottom = inset.Bottom; int left = inset.Left; int right = inset.Right; if (r.IsEmptyElement) return true; while (r.Read()) { switch (r.NodeType) { case System.Xml.XmlNodeType.Element: if (r.Name.Equals("Inset")) inInset = true; else if (r.Name.Equals("Color")) inColor = true; else if (r.Name.Equals("Sides")) inSides = true; else if (inInset || inSides) { if (r.Name.Equals("Bottom")) inBottom = true; else if (r.Name.Equals("Left")) inLeft = true; else if (r.Name.Equals("Right")) inRight = true; else if (r.Name.Equals("Top")) inTop = true; } else if (r.Name.Equals("Thickness")) inThickness = true; break; case System.Xml.XmlNodeType.Text: if (inInset) { if (inBottom) bottom = System.Xml.XmlConvert.ToInt32(r.Value); else if (inLeft) left = System.Xml.XmlConvert.ToInt32(r.Value); else if (inRight) right = System.Xml.XmlConvert.ToInt32(r.Value); else if (inTop) inset = new FarPoint.Win.Inset(left, System.Xml.XmlConvert.ToInt32(r.Value), right, bottom); } else if (inSides) { if (inBottom) this.bottom = System.Xml.XmlConvert.ToBoolean(r.Value.ToLower(System.Globalization.CultureInfo.InvariantCulture)); else if (inLeft) this.left = System.Xml.XmlConvert.ToBoolean(r.Value.ToLower(System.Globalization.CultureInfo.InvariantCulture)); else if (inRight) this.right = System.Xml.XmlConvert.ToBoolean(r.Value.ToLower(System.Globalization.CultureInfo.InvariantCulture)); else if (inTop) this.top = System.Xml.XmlConvert.ToBoolean(r.Value.ToLower(System.Globalization.CultureInfo.InvariantCulture)); } else if (inColor) color = FarPoint.Win.Serializer.DeserializeColorValue(r.Value); else if (inThickness) thickness = System.Xml.XmlConvert.ToInt32(r.Value); break; case System.Xml.XmlNodeType.EndElement: if (inInset && r.Name.Equals("Inset")) inInset = false; else if (inColor && r.Name.Equals("Color")) inColor = false; else if (inSides && r.Name.Equals("Sides")) inSides = false; else if (inInset || inSides) { if (inBottom && r.Name.Equals("Bottom")) inBottom = false; else if (inLeft && r.Name.Equals("Left")) inLeft = false; else if (inRight && r.Name.Equals("Right")) inRight = false; else if (inTop && r.Name.Equals("Top")) inTop = false; } else if (inThickness && r.Name.Equals("Thickness")) // サブクラスを逆シリアル化するため、ここで処理を終了します。 return true; break; } } return true; } |
Visual Basic |
コードのコピー
|
---|---|
' ISerializeSupportインタフェースの実装には、引数なしのコンストラクタが必要です。 ' パブリックである必要はありません。 Friend Sub New() color = SystemColors.WindowFrame thickness = 1 left = True top = True right = True bottom = True inset = New FarPoint.Win.Inset(1) End Sub ''' <summary> ''' オブジェクトを XML に保存します。 ''' </summary> ''' <param name="w">オブジェクトの保存先となる XmlTextWriter オブジェクトです。</param> ''' <returns>成功した場合は True を、そうでない場合は False を返します。</returns> Public Overridable Function Serialize(w As System.Xml.XmlTextWriter) As Boolean w.WriteStartElement("Inset") w.WriteElementString("Bottom", inset.Bottom.ToString()) w.WriteElementString("Left", inset.Left.ToString()) w.WriteElementString("Right", inset.Right.ToString()) w.WriteElementString("Top", inset.Top.ToString()) w.WriteEndElement() FarPoint.Win.Serializer.SerializeColor(color, "Color", w) w.WriteStartElement("Sides") w.WriteElementString("Bottom", bottom.ToString()) w.WriteElementString("Left", left.ToString()) w.WriteElementString("Right", right.ToString()) w.WriteElementString("Top", top.ToString()) w.WriteEndElement() w.WriteElementString("Thickness", thickness.ToString(System.Globalization.CultureInfo.InvariantCulture)) Return True End Function ''' <summary> ''' XML からオブジェクトをロードします。 ''' </summary> ''' <param name="r">オブジェクトをロードする XmlNodeReader です。</param> ''' <returns>成功した場合は True を、そうでない場合は False を返します。</returns> Public Overridable Function Deserialize(r As System.Xml.XmlNodeReader) As Boolean Dim inInset As Boolean = False Dim inBottom As Boolean = False Dim inLeft As Boolean = False Dim inRight As Boolean = False Dim inTop As Boolean = False Dim inColor As Boolean = False Dim inSides As Boolean = False Dim inThickness As Boolean = False Dim bottom As Integer = inset.Bottom Dim left As Integer = inset.Left Dim right As Integer = inset.Right If r.IsEmptyElement Then Return True End If While r.Read() Select Case r.NodeType Case System.Xml.XmlNodeType.Element If r.Name.Equals("Inset") Then inInset = True ElseIf r.Name.Equals("Color") Then inColor = True ElseIf r.Name.Equals("Sides") Then inSides = True ElseIf inInset OrElse inSides Then If r.Name.Equals("Bottom") Then inBottom = True ElseIf r.Name.Equals("Left") Then inLeft = True ElseIf r.Name.Equals("Right") Then inRight = True ElseIf r.Name.Equals("Top") Then inTop = True End If ElseIf r.Name.Equals("Thickness") Then inThickness = True End If Exit Select Case System.Xml.XmlNodeType.Text If inInset Then If inBottom Then bottom = System.Xml.XmlConvert.ToInt32(r.Value) ElseIf inLeft Then left = System.Xml.XmlConvert.ToInt32(r.Value) ElseIf inRight Then right = System.Xml.XmlConvert.ToInt32(r.Value) ElseIf inTop Then inset = New FarPoint.Win.Inset(left, System.Xml.XmlConvert.ToInt32(r.Value), right, bottom) End If ElseIf inSides Then If inBottom Then Me.bottom = System.Xml.XmlConvert.ToBoolean(r.Value.ToLower(System.Globalization.CultureInfo.InvariantCulture)) ElseIf inLeft Then Me.left = System.Xml.XmlConvert.ToBoolean(r.Value.ToLower(System.Globalization.CultureInfo.InvariantCulture)) ElseIf inRight Then Me.right = System.Xml.XmlConvert.ToBoolean(r.Value.ToLower(System.Globalization.CultureInfo.InvariantCulture)) ElseIf inTop Then Me.top = System.Xml.XmlConvert.ToBoolean(r.Value.ToLower(System.Globalization.CultureInfo.InvariantCulture)) End If ElseIf inColor Then color = FarPoint.Win.Serializer.DeserializeColorValue(r.Value) ElseIf inThickness Then thickness = System.Xml.XmlConvert.ToInt32(r.Value) End If Exit Select Case System.Xml.XmlNodeType.EndElement If inInset AndAlso r.Name.Equals("Inset") Then inInset = False ElseIf inColor AndAlso r.Name.Equals("Color") Then inColor = False ElseIf inSides AndAlso r.Name.Equals("Sides") Then inSides = False ElseIf inInset OrElse inSides Then If inBottom AndAlso r.Name.Equals("Bottom") Then inBottom = False ElseIf inLeft AndAlso r.Name.Equals("Left") Then inLeft = False ElseIf inRight AndAlso r.Name.Equals("Right") Then inRight = False ElseIf inTop AndAlso r.Name.Equals("Top") Then inTop = False End If ElseIf inThickness AndAlso r.Name.Equals("Thickness") Then ' サブクラスを逆シリアル化するため、ここで処理を終了します。 Return True End If Exit Select End Select End While Return True End Function |
次のサンプルコードは、派生クラスでの処理の実装例を示します。
C# |
コードのコピー
|
---|---|
// ISerializeSupport には、引数なしのコンストラクタが必要です。 // パブリックである必要はありません。 protected GradientLineBorder():base(SystemColors.WindowFrame, 1, true, true, true, true) { startColor = Color.Blue; endColor = Color.Green; } /// <summary> /// オブジェクトを XML に保存します。 /// </summary> /// <param name="w">オブジェクトの保存先となる XmlTextWriter オブジェクトです。</param> /// <returns>成功した場合は True を、そうでない場合は False を返します。</returns> public override bool Serialize(System.Xml.XmlTextWriter w) { if (!base.Serialize(w)) return false; FarPoint.Win.Serializer.SerializeColor(startColor, "StartColor", w); FarPoint.Win.Serializer.SerializeColor(endColor, "EndColor", w); return true; } /// <summary> /// XML からオブジェクトをロードします。 /// </summary> /// <param name="r">オブジェクトをロードする XmlNodeReader です。</param> /// <returns>成功した場合は True を、そうでない場合は False を返します。</returns> public override bool Deserialize(System.Xml.XmlNodeReader r) { bool inStartColor = false; bool inEndColor = false; if (r.IsEmptyElement) return true; if (!base.Deserialize(r)) return false; while (r.Read()) { switch (r.NodeType) { case System.Xml.XmlNodeType.Element: if (r.Name.Equals("StartColor")) inStartColor = true; else if (r.Name.Equals("EndColor")) inEndColor = true; break; case System.Xml.XmlNodeType.Text: if (inStartColor) startColor = FarPoint.Win.Serializer.DeserializeColorValue(r.Value); else if (inEndColor) endColor = FarPoint.Win.Serializer.DeserializeColorValue(r.Value); break; case System.Xml.XmlNodeType.EndElement: if (inStartColor && r.Name.Equals("StartColor")) inStartColor = false; else if (inEndColor && r.Name.Equals("EndColor")) // サブクラスを逆シリアル化するため、ここで処理を終了します。 return true; break; } } return true; } |
Visual Basic |
コードのコピー
|
---|---|
' ISerializeSupport には、引数なしのコンストラクタが必要です。 ' パブリックである必要はありません。 Protected Sub New() MyBase.New(SystemColors.WindowFrame, 1, True, True, True, True) startColor = Color.Blue endColor = Color.Green End Sub ''' <summary> ''' オブジェクトを XML に保存します。 ''' </summary> ''' <param name="w">オブジェクトの保存先となる XmlTextWriter オブジェクトです。</param> ''' <returns>成功した場合は True を、そうでない場合は False を返します。</returns> Public Overrides Function Serialize(w As System.Xml.XmlTextWriter) As Boolean If Not MyBase.Serialize(w) Then Return False End If FarPoint.Win.Serializer.SerializeColor(startColor, "StartColor", w) FarPoint.Win.Serializer.SerializeColor(endColor, "EndColor", w) Return True End Function ''' <summary> ''' XML からオブジェクトをロードします。 ''' </summary> ''' <param name="r">オブジェクトをロードする XmlNodeReader です。</param> ''' <returns>成功した場合は True を、そうでない場合は False を返します。</returns> Public Overrides Function Deserialize(r As System.Xml.XmlNodeReader) As Boolean Dim inStartColor As Boolean = False Dim inEndColor As Boolean = False If r.IsEmptyElement Then Return True End If If Not MyBase.Deserialize(r) Then Return False End If While r.Read() Select Case r.NodeType Case System.Xml.XmlNodeType.Element If r.Name.Equals("StartColor") Then inStartColor = True ElseIf r.Name.Equals("EndColor") Then inEndColor = True End If Exit Select Case System.Xml.XmlNodeType.Text If inStartColor Then startColor = FarPoint.Win.Serializer.DeserializeColorValue(r.Value) ElseIf inEndColor Then endColor = FarPoint.Win.Serializer.DeserializeColorValue(r.Value) End If Exit Select Case System.Xml.XmlNodeType.EndElement If inStartColor AndAlso r.Name.Equals("StartColor") Then inStartColor = False ElseIf inEndColor AndAlso r.Name.Equals("EndColor") Then ' サブクラスを逆シリアル化するため、ここで処理を終了します。 Return True End If Exit Select End Select End While Return True End Function |
次のサンプルコードは、XMLの属性にColorを保存する例です。先の例の、XMLの要素にColorを保存する方法に比べ、コード量が少なく、簡易的な方法です。
C# |
コードのコピー
|
---|---|
/// <summary> /// オブジェクトを XML に保存します。 /// </summary> /// <param name="w">オブジェクトの保存先となる XmlTextWriter オブジェクトです。</param> /// <returns>成功した場合は True を、そうでない場合は False を返します。</returns> public override bool Serialize(System.Xml.XmlTextWriter w) { w.WriteAttributeString("startColor", FarPoint.Win.Serializer.SerializeColorValue(startColor)); w.WriteAttributeString("endColor", FarPoint.Win.Serializer.SerializeColorValue(endColor)); return base.Serialize(w); } /// <summary> /// XML からオブジェクトをロードします。 /// </summary> /// <param name="r">オブジェクトをロードする XmlNodeReader です。</param> /// <returns>成功した場合は True を、そうでない場合は False を返します。</returns> public override bool Deserialize(System.Xml.XmlNodeReader r) { if (r.MoveToAttribute("startColor")) startColor = FarPoint.Win.Serializer.DeserializeColorValue(r.Value); if (r.MoveToAttribute("endColor")) endColor = FarPoint.Win.Serializer.DeserializeColorValue(r.Value); return base.Deserialize(r); } |
Visual Basic |
コードのコピー
|
---|---|
''' <summary> ''' オブジェクトを XML に保存します。 ''' </summary> ''' <param name="w">オブジェクトの保存先となる XmlTextWriter オブジェクトです。</param> ''' <returns>成功した場合は True を、そうでない場合は False を返します。</returns> Public Overrides Function Serialize(w As System.Xml.XmlTextWriter) As Boolean w.WriteAttributeString("startColor", FarPoint.Win.Serializer.SerializeColorValue(startColor)) w.WriteAttributeString("endColor", FarPoint.Win.Serializer.SerializeColorValue(endColor)) Return MyBase.Serialize(w) End Function ''' <summary> ''' XML からオブジェクトをロードします。 ''' </summary> ''' <param name="r">オブジェクトをロードする XmlNodeReader です。</param> ''' <returns>成功した場合は True を、そうでない場合は False を返します。</returns> Public Overrides Function Deserialize(r As System.Xml.XmlNodeReader) As Boolean If r.MoveToAttribute("startColor") Then startColor = FarPoint.Win.Serializer.DeserializeColorValue(r.Value) End If If r.MoveToAttribute("endColor") Then endColor = FarPoint.Win.Serializer.DeserializeColorValue(r.Value) End If Return MyBase.Deserialize(r) End Function |