忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

各種オブジェクトのコピーができるディープコピー(BinaryFormatter,MemoryStream,Serialize,Deserialize)

クラスや構造体などのオブジェクトのクローンコピーを作りたい場合があります。 各種のオブジェクトのデータを退避する時に、一括でクローンが作れれば便利なのですが、BinaryFormatter クラスを 使って、シリアライズとデシリアライズを行うことでできます。

以下のソースにその関数を記します。 BinaryFormatterSerialize メソッドによりコピー元のオブジェクトをメモリストリームに展開します。 その後メモリストリームの内容を別のオブジェクトにデシリアライズを行います。

ディープコピー関数

    ''' -----------------------------------------------------------------------
    ''' 
    ''' オブジェクトのコピー
    ''' 
    ''' Type
    ''' <param name="objSrc">コピー元のオブジェクト</param>
    ''' クローンオブジェクト
    ''' -----------------------------------------------------------------------
    Function DeepCopy(Of T)(ByVal objSrc As T) As T
        'クローンオブジェクト宣言
        Dim objRet As T
        'BinaryFormatterクラス
        Dim b As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
        'バイト処理を行うメモリストリーム
        Dim ms As New System.IO.MemoryStream()
        Try
            'シリアライズ(MemoryStreamにシリアライズ化して展開)
            b.Serialize(ms, objSrc)
            'メモリ位置を初期化
            ms.Position = 0
            'デシリアライズ(MemoryStreamからデシリアライズ化してオブジェクトに戻す)
            objRet = CType(b.Deserialize(ms), T)

        Catch ex As Exception
            '
        Finally
            ms.Close()
        End Try
        'クローンを戻す
        Return objRet
    End Function

この関数を使う例を以下に記します。

以下のソースでは、 DeepCopy 用のテストクラスとして clsCopyTest と、 テスト構造体として structCopyTest を宣言しています。
それぞれのクラス、構造体ともに <Serializable()> を指定しています。 これが無いとシリアライズ処理ができないので注意が必要です。

ディープコピー関数の使用例

    ''' 
    ''' DeepCopy 用のテストクラス
    ''' 
    <Serializable()> _
    Private Class clsCopyTest
        Public _strTest As String
        Public _intTest As Integer

        'コンストラクタ
        Sub New(ByVal strTest As String, ByVal intTest As Integer)
            Me._strTest = strTest
            Me._intTest = intTest
        End Sub

        '内部データの表示用の文字列取得
        Function GetDataString() As String
            Return "strTest=" & Me._strTest & vbCrLf & "intTest=" & Me._intTest.ToString
        End Function
    End Class

    ''' 
    ''' DeepCopy 用のテスト構造体
    ''' 
    <Serializable()> _
    Private Class structCopyTest
        Private _strTest As String
        Private _intTest As Integer

        'コンストラクタ
        Sub New(ByVal strTest As String, ByVal intTest As Integer)
            Me._strTest = strTest
            Me._intTest = intTest
        End Sub

        '内部データの表示用の文字列取得
        Function GetDataString() As String
            Return "strTest=" & Me._strTest & vbCrLf & "intTest=" & Me._intTest.ToString
        End Function
    End Class

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'クラスでのテスト
        Dim clsT As New clsCopyTest("ABCD", 100)        'クラス生成
        Dim clsCloneT As clsCopyTest = DeepCopy(clsT)   'クラスクローンコピー
        clsCloneT._strTest &= "..."                     'クローンのデータを更新
        clsCloneT._intTest *= 100
        'クラスのメソッドで内容表示
        MsgBox("Src  :" & vbCrLf & clsT.GetDataString & vbCrLf & "Clone:" & vbCrLf & clsCloneT.GetDataString)

        '構造体でのテスト
        Dim strucT As New structCopyTest("EFGHI", 200)          '構造体生成
        Dim strucCloneT As structCopyTest = DeepCopy(strucT)    '構造体クローンコピー
        MsgBox(strucCloneT.GetDataString)                       '構造体のメソッド
    End Sub

ボタン処理内でクラスのテストと、構造体のテストを行っています。 クラスの方は、クローンコピーの値を少し変化を加えています。 その後、それぞれのクラス内の値を見てみると、両方の値が異なることが分かります。


関連する記事

クラスのコピーについて(Object.MemberwiseClone)











PR

コメント

コメントを書く