.NET CoreでBinaryFormatterを使用しないディープコピーの実装方法

はじめに

.NET Coreでは、セキュリティや互換性の問題から BinaryFormatter の使用が推奨されていません。そのため、ディープコピー(*)を実現する別の方法を使用する必要があります。この記事では、BinaryFormatter の代わりに XmlSerializer を使用してディープコピーを行う方法を紹介します。

*ディープコピー…オブジェクトの完全な複製を作成するプロセス。これはオブジェクト自体だけでなく、そのオブジェクトが参照するすべてのオブジェクトも含めて複製すること。

前提条件

・開発ツール:VisualStudio2022

・開発言語:C#

BinaryFormatterを使用したディープコピー(.NET Framework向け)

public static class ObjectHelper
{
    public static T DeepCloneBinaryFormatter<T>(this T src)
    {
        using (var memoryStream = new MemoryStream())
        {
            var binaryFormatter = new BinaryFormatter();
            binaryFormatter.Serialize(memoryStream, src); // シリアライズ
            memoryStream.Seek(0, SeekOrigin.Begin);
            return (T)binaryFormatter.Deserialize(memoryStream); // デシリアライズ
        }
    }
}

この方法では、オブジェクトをバイナリ形式にシリアライズ(*)し、その後デシリアライズ(*)することで、新しいオブジェクトのインスタンスを生成します。しかし、BinaryFormatter は .NET Core では非推奨です。

*シリアライズ…最初にオブジェクトのデータを連続したバイナリデータ(0と1のデータ)に変換すること

*デシリアライズ…シリアライズで変換されたバイナリデータを使って、新しいオブジェクトを生成すること

XmlSerializerを使用したディープコピー(.NET Core対応)

次に、BinaryFormatter の代替として XmlSerializer を使用したディープコピーの実装例を紹介します。この方法は、.NET Core でも使用可能です。

public static class ObjectHelper
{
    public static T DeepCloneXmlSerializer<T>(this T src)
    {
        // XmlSerializerのインスタンスを作成
        var xmlserializer = new XmlSerializer(typeof(T));

        // MemoryStreamを使用してシリアライゼーション
        using (var memoryStream = new MemoryStream())
        {
            xmlserializer.Serialize(memoryStream, src);

            // 読み取り位置をストリームの始まりに戻す
            memoryStream.Seek(0, SeekOrigin.Begin);

            // デシリアライゼーション
            return (T)xmlserializer.Deserialize(memoryStream);
        }
    }
}

この方法では、オブジェクトをXML形式にシリアライズし、その後デシリアライズすることで新しいインスタンスを生成します。

XmlSerializer を使用することで、.NET Core でも安全にディープコピーを行うことができます。

ディープコピーの利点と注意点

ディープコピーを使用することで、オブジェクトの完全な複製を作成できるため、元のオブジェクトとコピーされたオブジェクトが独立して操作できます。これにより、オブジェクトの変更が他の部分に影響を与えることを防ぐことができます。

ただし、XmlSerializerを使用する際には、いくつかの注意点があります:

  1. デフォルトコンストラクタの必要性: XmlSerializerは、デフォルトコンストラクタがないクラスやプロパティがprivateであるクラスをシリアライズできません。そのため、すべてのシリアライズ対象のクラスにはデフォルトコンストラクタを定義する必要があります。
  2. 非対応型の考慮: XmlSerializerは、一部の型(例:Dictionaryなど)を直接シリアライズできません。これらの型を使用する場合、代替手段として別のシリアライゼーション手法を検討するか、対応可能な形式に変換する必要があります。

まとめ

BinaryFormatter はセキュリティの観点から非推奨となっているため、.NET Core では XmlSerializer などの他のシリアライゼーション手法を使用することが推奨されます。この記事で紹介した XmlSerializer を使用した方法は、簡単に実装でき、安全にディープコピーを行うことができます。ぜひ試してみてください。