どんなオブジェクトでもコピーできる汎用のディープコピー処理(ICloneable, MemberWiseClone, Serializable, BinaryFormatter, MemoryStream)
シリアライズを利用した汎用のオブジェクトのディープコピー処理について整理しました。BinaryFormatterを使用してMemoryStreamに対してシリアライズ/デシリアライズを行いオブジェクトのメモリイメージのコピーを作成するテクニックです。理論上、Serializable属性を付与したすべてのオブジェクトに対してディープコピーが可能になります。
ICloneableインタフェース、MemberWiseCloneメソッドを使用したシャローコピーについては以下の記事を参考にしてください。
■オブジェクトのコピー。ICloneableインタフェース、MemberWiseClone、シリアライズを利用したインスタンスのコピー。
http://d.hatena.ne.jp/tekk/20091012/1255362429
C#
ジェネリック版と拡張メソッド版の2種を用意してみました。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;namespace DeepCopyCSharp
{
class Program
{
[Serializable()]
public class item{
public int id;
public string name;
}static void Main(string[] args)
{item a = new item();
a.id = 12345;
a.name = "hello";item b;
// 拡張メソッド
b = (item)a.DeepCopy();// ジェネリックメソッド
b = DeepCopyHelper.DeepCopy
- (a);
b.id = 54635;
Console.ReadLine();
}}
static class DeepCopyUtils
{
public static object DeepCopy(this object target)
{object result;
BinaryFormatter b = new BinaryFormatter();MemoryStream mem = new MemoryStream();
try
{
b.Serialize(mem, target);
mem.Position = 0;
result = b.Deserialize(mem);
}
finally
{
mem.Close();
}return result;
}
}public static class DeepCopyHelper
{
public static T DeepCopy(T target)
{T result;
BinaryFormatter b = new BinaryFormatter();MemoryStream mem = new MemoryStream();
try
{
b.Serialize(mem, target);
mem.Position = 0;
result = (T)b.Deserialize(mem);
}
finally
{
mem.Close();
}return result;
}
}}
VB.NET
ジェネリック版と拡張メソッド版の2種を用意してみました。
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Runtime.CompilerServicesPublic Class Form1
_
Public Class item
Public id As Integer
Public name As String
End ClassPrivate Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim a As New item
a.id = 12345
a.name = "hello"' 拡張メソッド
Dim b As item = CType(a.DeepCopy, item)' ジェネリック
b = DeepCopyHelper.DeepCopy(a)b.id = 54354
MsgBox(a.id)
End Sub
End Class
Public Module DeepCopyUtils
_
Public Function DeepCopy(ByVal target As Object) As ObjectDim result As Object
Dim b As New BinaryFormatterDim mem As New System.IO.MemoryStream()
Try
b.Serialize(mem, target)
mem.Position = 0
result = b.Deserialize(mem)Finally
mem.Close()
End Try
Return result
End Function
End Module
Public Class DeepCopyHelper
Public Shared Function DeepCopy(Of T)(ByVal target As T) As T
Dim result As T
Dim b As New BinaryFormatterDim mem As New System.IO.MemoryStream()
Try
b.Serialize(mem, target)
mem.Position = 0
result = CType(b.Deserialize(mem), T)Finally
mem.Close()
End Try
Return result
End Function
End Class