異なるクラスでもコピーする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;
}
ジェネリック版と拡張メソッド版の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;
}
}
}
ジェネリック版と拡張メソッド版の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 ObjectDim 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 = 0result = destSerializer.Deserialize(mem)
Finally
mem.Close()
End Try
Return result
End Function
End Class