異なるクラスでもコピーするXMLSerializerを使用した汎用のディープコピー処理(ICloneable, MemberWiseClone, Serializable, XmlSerializer, MemoryStream)

前回、どんなオブジェクトでもコピーできる処理を作ってみました。今回は、クラスが異なる場合でもプロパティの名前さえ一致すればディープコピーできる処理について整理してみました。

どんなオブジェクトでもコピーできる汎用のディープコピー処理(ICloneable, MemberWiseClone, Serializable, BinaryFormatter, MemoryStream)
http://d.hatena.ne.jp/tekk/20100131/1264913887

クラスが異なるとコピーすることができません。これはシリアライズ/デシリアライズする際にクラスが異なるとエラーが発生するからですが、逆に考えれば、シリアライズ/デシリアライズする際にクラスが一致するように調整すればディープコピーができるということです。

そこでXMLSerializerを使います。シリアライズの形式をXMLにし、異なるクラスのXMLのタグ名を一致させるように属性を指定して、異なるクラスでもディープコピーを行うようにします。

[System.Serializable()]
[System.Xml.Serialization.XmlRoot("Item")]
public class SrcClass
{
[System.Xml.Serialization.XmlElement("id")]
public int id = 0;
[System.Xml.Serialization.XmlElement("name")]
public String name = String.Empty;
}

[System.Serializable()]
[System.Xml.Serialization.XmlRoot("Item")]
public class DestClass
{
[System.Xml.Serialization.XmlElement("id")]
public int id = 0;
[System.Xml.Serialization.XmlElement("name")]
public String name = String.Empty;
}

C#

ジェネリック版と拡張メソッド版の2種を用意してみました。

using System;
using System.IO;

namespace DeepCopyTestCSharp
{

[System.Serializable()]
[System.Xml.Serialization.XmlRoot("Item")]
public class SrcClass
{
[System.Xml.Serialization.XmlElement("id")]
public int id = 0;
[System.Xml.Serialization.XmlElement("name")]
public String name = String.Empty;
}

[System.Serializable()]
[System.Xml.Serialization.XmlRoot("Item")]
public class DestClass
{
[System.Xml.Serialization.XmlElement("id")]
public int id = 0;
[System.Xml.Serialization.XmlElement("name")]
public String name = String.Empty;
}

class Program
{
static void Main(string[] args)
{

SrcClass srcObject = new SrcClass();

srcObject.id = 1;
srcObject.name = "aa";

DestClass destObject = null;

destObject = (DestClass)srcObject.DeepCopyByXML(typeof(SrcClass ), typeof(DestClass));
destObject = (DestClass)DeepCopyHelper.DeepCopyByXML(srcObject, typeof(DestClass));

}
}

static class DeepCopyUtils
{

public static object DeepCopyByXML(this object srcObject,
Type srcType,
Type destType)
{

object result;
System.Xml.Serialization.XmlSerializer srcSerializer = new System.Xml.Serialization.XmlSerializer(srcType);
System.Xml.Serialization.XmlSerializer destSerializer = new System.Xml.Serialization.XmlSerializer(destType);

MemoryStream mem = new MemoryStream();

try
{
srcSerializer.Serialize(mem, srcObject);
mem.Position = 0;
result = destSerializer.Deserialize(mem);
}
finally
{
mem.Close();
}

return result;

}
}

public static class DeepCopyHelper
{
public static Object DeepCopyByXML(T srcTarget, Type destType)
{

Object result;

System.Xml.Serialization.XmlSerializer srcSerializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
System.Xml.Serialization.XmlSerializer destSerializer = new System.Xml.Serialization.XmlSerializer(destType);

MemoryStream mem = new MemoryStream();

try
{
srcSerializer.Serialize(mem, srcTarget);
mem.Position = 0;
result = destSerializer.Deserialize(mem);
}
finally
{
mem.Close();
}

return result;

}
}


}

VB.NET

ジェネリック版と拡張メソッド版の2種を用意してみました。


Imports System.Runtime.CompilerServices

_
_
Public Class SrcClass
_
Public id As Integer
_
Public name As String
End Class

_
_
Public Class DestClass
_
Public id As Integer
_
Public name As String
End Class


Module Module1

Sub Main()

Dim srcObject As New SrcClass

srcObject.id = 1
srcObject.name = "aa"

Dim destObject As DestClass = Nothing

destObject = CType(srcObject.DeepCopyByXML(GetType(SrcClass), GetType(DestClass)), DestClass)

destObject = CType(DeepCopyHelper.DeepCopyByXML(srcObject, GetType(DestClass)), DestClass)

End Sub

End Module

Public Module DeepCopyUtils

_
Public Function DeepCopyByXML(ByVal srcObject As Object, _
ByVal srcType As Type, _
ByVal destType As Type) As Object

Dim result As Object

Dim srcSerializer As New Xml.Serialization.XmlSerializer(srcType)
Dim destSerializer As New Xml.Serialization.XmlSerializer(destType)

Dim mem As New System.IO.MemoryStream()

Try

srcSerializer.Serialize(mem, srcObject)
mem.Position = 0
result = destSerializer.Deserialize(mem)

Finally

mem.Close()

End Try

Return result

End Function

End Module

Public Class DeepCopyHelper

Public Shared Function DeepCopyByXML(Of T)(ByVal srcObject As T, ByVal destType As Type) As Object

Dim result As Object

Dim srcSerializer As New Xml.Serialization.XmlSerializer(GetType(T))
Dim destSerializer As New Xml.Serialization.XmlSerializer(destType)

Dim mem As New System.IO.MemoryStream()

Try

srcSerializer.Serialize(mem, srcObject)
mem.Position = 0

result = destSerializer.Deserialize(mem)

Finally

mem.Close()

End Try

Return result

End Function

End Class