개발관련/other

딥 클로닝 개체

Rateye 2021. 11. 18. 10:13
728x90
반응형
질문 : 딥 클로닝 개체

다음과 같이하고 싶습니다.

MyObject myObj = GetMyObj(); // Create and fill a new object
MyObject newObj = myObj.Clone();

그런 다음 원래 개체에 반영되지 않은 새 개체를 변경합니다.

저는이 기능이 자주 필요하지 않으므로 필요할 때 새 객체를 만든 다음 각 속성을 개별적으로 복사하는 방법을 사용했지만 항상 더 좋고 우아한 처리 방법이 있다는 느낌을받습니다. 그 상황.

원본 개체에 변경 사항이 반영되지 않고 복제 된 개체를 수정할 수 있도록 개체를 복제하거나 전체 복사하려면 어떻게해야합니까?

답변

한 가지 접근 방식은 ICloneable 인터페이스 를 구현하는 것이지만 (여기 에 설명되어 있으므로 역류하지 않겠습니다) 여기에 얼마 전에 The Code Project에서 찾은 멋진 딥 클론 객체 복사기가 있습니다. 다른 곳에서 언급했듯이 객체를 직렬화 할 수 있어야합니다.

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
public static class ObjectCopier
{
    /// <summary>
    /// Perform a deep copy of the object via serialization.
    /// </summary>
    /// <typeparam name="T">The type of object being copied.</typeparam>
    /// <param name="source">The object instance to copy.</param>
    /// <returns>A deep copy of the object.</returns>
    public static T Clone<T>(T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", nameof(source));
        }

        // Don't serialize a null object, simply return the default for that object
        if (ReferenceEquals(source, null)) return default;

        using var Stream stream = new MemoryStream();
        IFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, source);
        stream.Seek(0, SeekOrigin.Begin);
        return (T)formatter.Deserialize(stream);
    }
}

아이디어는 개체를 직렬화 한 다음 새로운 개체로 역 직렬화하는 것입니다. 이점은 객체가 너무 복잡해지면 모든 것을 복제하는 것에 대해 걱정할 필요가 없다는 것입니다.

C # 3.0의 새로운 확장 메서드 를 사용하려는 경우 다음 서명을 갖도록 메서드를 변경합니다.

public static T Clone<T>(this T source)
{
   // ...
}

이제 메서드 호출은 단순히 objectBeingCloned.Clone(); .

편집 (2015 년 1 월 10 일) 최근에 (Newtonsoft) Json을 사용하여이 작업을 시작했음을 언급하기 위해 이것을 다시 방문 할 것이라고 생각했습니다 . 더 가벼워 야하며 [Serializable] 태그의 오버 헤드를 피해야합니다. ( NB @atconway는 개인 구성원이 JSON 방법을 사용하여 복제되지 않는다는 의견을 지적했습니다)

/// <summary>
/// Perform a deep Copy of the object, using Json as a serialization method. NOTE: Private members are not cloned using this method.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T CloneJson<T>(this T source)
{            
    // Don't serialize a null object, simply return the default for that object
    if (ReferenceEquals(source, null)) return default;

    // initialize inner objects individually
    // for example in default constructor some list property initialized with some values,
    // but in 'source' these items are cleaned -
    // without ObjectCreationHandling.Replace default constructor values will be added to result
    var deserializeSettings = new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace};

    return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
}
출처 : https://stackoverflow.com/questions/78536/deep-cloning-objects
728x90
반응형