Derin klonlama nesneleri


Al─▒nan cevaba git


Gibi bir ┼čey yapmak istiyorum:

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

Ard─▒ndan, orijinal nesneye yans─▒t─▒lmayan yeni nesnede de─či┼čiklikler yap─▒n.

S─▒k s─▒k bu i┼čleve ihtiyac─▒m yok, bu y├╝zden gerekti─činde, yeni bir nesne yaratmaya ve ard─▒ndan her bir m├╝lk├╝ ayr─▒ ayr─▒ kopyalamaya ├žal─▒┼čt─▒m, ancak her zaman daha iyi ya da daha zarif bir kullan─▒m y├Ântemi oldu─ču hissi uyand─▒r─▒yor. durum.

Bir nesneyi, klonlanan nesnenin, orijinal nesneye herhangi bir de─či┼čiklik yap─▒lmadan de─či┼čtirilebilmesi i├žin de─či┼čtirilebilmesi i├žin nas─▒l klonlayabilir veya derin kopyalayabilirim?


2109









Cevap say─▒s─▒n─▒ say: 30






Standart uygulama, ICloneable aray├╝z├╝ uygulamak iken ( burada tarif edilir , b├Âylece peri┼čan olmayaca─č─▒m), i┼čte bir s├╝re ├Ânce Kod Projesinde buldu─čum ve e┼čyalar─▒m─▒za ekledi─čim g├╝zel bir derin klon nesne fotokopi makinesi .

Ba┼čka bir yerde de belirtildi─či gibi, nesnelerinizin seri hale getirilebilir olmas─▒n─▒ gerektirir.

 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.
    /// </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 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 (Object.ReferenceEquals(source, null))
        {
            return default(T);
        }

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

Buradaki fikir, nesnenizi seri hale getirmesi ve ard─▒ndan yeni bir nesneye seri hale getirmesidir. Bunun yarar─▒, bir nesne ├žok karma┼č─▒kla┼čt─▒─č─▒nda her ┼čeyi klonlamak konusunda kendinizi endi┼čelendirmenize gerek olmamas─▒d─▒r.

Ve uzatma y├Ântemlerinin kullan─▒m─▒yla (ba┼člang─▒├žta referans al─▒nan kaynaktan da):

C # 3.0'─▒n yeni uzant─▒ y├Ântemlerini kullanmay─▒ tercih ediyorsan─▒z , a┼ča─č─▒daki imzay─▒ alacak ┼čekilde y├Ântemi de─či┼čtirin:

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

┼×imdi y├Ântem ├ža─čr─▒s─▒ basit├že olur objectBeingCloned.Clone(); .

EDIT (10 Ocak 2015) Son zamanlarda (Newtonsoft) Json kullanmaya ba┼člad─▒─č─▒mdan, daha hafif olmas─▒ gerekti─čini ve [Seri hale getirilebilir] etiketlerinin ek y├╝k├╝nden ka├ž─▒nd─▒─č─▒n─▒ s├Âylememe ra─čmen, bunu tekrar ziyaret edece─čimi d├╝┼č├╝nd├╝m . ( NB @atconway, JSON y├Ântemi kullan─▒larak ├Âzel ├╝yelerin klonlanmad─▒─č─▒n─▒ belirtti.

 /// <summary>
/// Perform a deep Copy of the object, using Json as a serialisation 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 (Object.ReferenceEquals(source, null))
    {
        return default(T);
    }

    // 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);
}
 

1647







├ço─čunlukla ilkel ve listelerden olu┼čan basit nesneler i├žin bir klonlay─▒c─▒ istedim. Nesneniz JSON serile┼čtirilebilir kutunun d─▒┼č─▒ndaysa, bu y├Ântem hile yapar. Bu, klonlanm─▒┼č s─▒n─▒fta hi├žbir aray├╝z veya uygulama gerektirmez, sadece JSON.NET gibi bir JSON seri hale getirici gerektirir.

 public static T Clone<T>(T source)
{
    var serialized = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(serialized);
}
 

Ayr─▒ca, bu eklenti y├Ântemini kullanabilirsiniz

 public static class SystemExtension
{
    public static T Clone<T>(this T source)
    {
        var serialized = JsonConvert.SerializeObject(source);
        return JsonConvert.DeserializeObject<T>(serialized);
    }
}
 

263







Kullanmamaya nedeni ICloneable oldu─ču de─čil , genel bir aray├╝ze sahip olmad─▒─č─▒ i├žin. Kullanmamak i├žin nedeni belirsiz olmas─▒d─▒r . S─▒─č m─▒ yoksa derin bir kopya m─▒ edindi─činiz belli de─čil; uygulay─▒c─▒ya kalm─▒┼č.

Evet, MemberwiseClone s─▒─č bir kopya ├ž─▒karsa da tam tersi MemberwiseClone de─čildir Clone ; belki de olmayan bir ┼čey olurdu DeepClone . ICloneable aray├╝z├╝ ├╝zerinden bir nesneyi kulland─▒─č─▒n─▒zda, alttaki nesnenin ne t├╝r bir klonlama ger├žekle┼čtirdi─čini bilemezsiniz. (Ve XML yorumlar─▒ netle┼čtirmez, ├ž├╝nk├╝ nesnenin Clone y├Ântemindeki yorumlar yerine arabirim yorumlar─▒n─▒ al─▒rs─▒n─▒z.)

Genelde yapt─▒─č─▒m ┼čey Copy , tam olarak istedi─čimi yapan bir y├Ântem yapmak .


169







Buraya ba─čl─▒ se├ženeklerin bir├žo─ču ve bu sorunla ilgili olas─▒ ├ž├Âz├╝mler hakk─▒nda ├žok fazla okumadan sonra, t├╝m se├ženeklerin Ian P'nin ba─člant─▒s─▒nda olduk├ža iyi bir ┼čekilde ├Âzetlendi─čine inan─▒yorum (di─čer t├╝m se├ženekler bunlar─▒n varyasyonlar─▒d─▒r) ve en iyi ├ž├Âz├╝m sa─članm─▒┼čt─▒r Pedro77 adl─▒ kullan─▒c─▒n─▒n ba─člant─▒s─▒ soru yorumlar─▒na.

Bu y├╝zden bu 2 referans─▒n ilgili k─▒s─▒mlar─▒n─▒ buraya kopyalayaca─č─▒m. Bu ┼čekilde sahip olabiliriz:

C keskin nesneleri klonlamak i├žin yap─▒lacak en iyi ┼čey!

Her ┼čeyden ├Ânce, hepsi bizim se├ženeklerimiz:

─░fade A─ča├žlar taraf─▒ndan makale H─▒zl─▒ Derin Kopya da Diziselle┼čtirme, Yans─▒ma ve ─░fade A─ča├žlar taraf─▒ndan klonlama performans kar┼č─▒la┼čt─▒rmas─▒n─▒ vard─▒r.

Neden ICloneable'├╝ se├žiyorum (yani manuel olarak)

Say─▒n Venkat Subramaniam (burada fazladan ba─člant─▒) nedenini ├žok ayr─▒nt─▒l─▒ olarak a├ž─▒klar .

T├╝m makalesi, 3 nesne kullanarak ├žo─ču durumda uygulanabilir olmaya ├žal─▒┼čan bir ├Ârnek etraf─▒nda d├Ân├╝yor: Ki┼či , Beyin ve ┼×ehir . Ayn─▒ ┼čehirden kendi beynine sahip olan birini klonlamak istiyoruz. T├╝m problemleri hayal edebilir ya da yukar─▒daki di─čer y├Ântemlerden herhangi birini makaleyi getirebilir veya okuyabilirsiniz.

Bu benim sonucumun biraz de─či┼čtirilmi┼č hali:

Bir nesneyi New s─▒n─▒f ad─▒n─▒n ard─▒ndan belirterek kopyalamak, genellikle geni┼čletilemeyen bir koda yol a├žar. Prototip modelinin uygulanmas─▒ olan klon kullan─▒lmas─▒, bunu ba┼čarman─▒n daha iyi bir yoludur. Bununla birlikte, klonu C # (ve Java) da sa─čland─▒─č─▒ gibi kullanmak da olduk├ža problemli olabilir. Korumal─▒ (halka a├ž─▒k olmayan) bir kopya yap─▒c─▒s─▒ sa─člamak ve bunu klonlama y├Ânteminden ├ža─č─▒rmak daha iyidir. Bu bize bir nesneyi bir s─▒n─▒f─▒n kendi ├Ârne─čine olu┼čturma g├Ârevini devretme, b├Âylece geni┼čletilebilirlik sa─člama ve ayr─▒ca korumal─▒ kopya kurucuyu kullanarak nesneleri g├╝venli bir ┼čekilde olu┼čturma yetene─či verir.

Umar─▒m bu uygulama i┼čleri netle┼čtirebilir:

 public class Person : ICloneable
{
    private final Brain brain; // brain is final since I do not want 
                // any transplant on it once created!
    private int age;
    public Person(Brain aBrain, int theAge)
    {
        brain = aBrain; 
        age = theAge;
    }
    protected Person(Person another)
    {
        Brain refBrain = null;
        try
        {
            refBrain = (Brain) another.brain.clone();
            // You can set the brain in the constructor
        }
        catch(CloneNotSupportedException e) {}
        brain = refBrain;
        age = another.age;
    }
    public String toString()
    {
        return "This is person with " + brain;
        // Not meant to sound rude as it reads!
    }
    public Object clone()
    {
        return new Person(this);
    }
    ÔÇŽ
}
 

┼×imdi, bir s─▒n─▒f─▒n Ki┼či'den geldi─čini d├╝┼č├╝n├╝n.

 public class SkilledPerson extends Person
{
    private String theSkills;
    public SkilledPerson(Brain aBrain, int theAge, String skills)
    {
        super(aBrain, theAge);
        theSkills = skills;
    }
    protected SkilledPerson(SkilledPerson another)
    {
        super(another);
        theSkills = another.theSkills;
    }

    public Object clone()
    {
        return new SkilledPerson(this);
    }
    public String toString()
    {
        return "SkilledPerson: " + super.toString();
    }
}
 

A┼ča─č─▒daki kodu ├žal─▒┼čt─▒rmay─▒ deneyebilirsiniz:

 public class User
{
    public static void play(Person p)
    {
        Person another = (Person) p.clone();
        System.out.println(p);
        System.out.println(another);
    }
    public static void main(String[] args)
    {
        Person sam = new Person(new Brain(), 1);
        play(sam);
        SkilledPerson bob = new SkilledPerson(new SmarterBrain(), 1, "Writer");
        play(bob);
    }
}
 

├ťretilen ├ž─▒kt─▒:

 This is person with [email protected]
This is person with [email protected]
SkilledPerson: This is person with [email protected]
SkilledPerson: This is person with [email protected]
 

E─čer g├Âzlemlenen say─▒da obje tutarsak, burada uygulanan klonun obje say─▒s─▒n─▒ do─čru tutaca─č─▒n─▒ g├Âzlemleyin.


108







Bir kopya kurucuyu bir klona tercih ederim. Ama├ž daha a├ž─▒k.


81


2008-09-17





T├╝m genel ├Âzellikleri kopyalamak i├žin basit bir uzatma y├Ântemi. Herhangi bir nesne i├žin ├žal─▒┼č─▒r ve yok olmaya s─▒n─▒f─▒n─▒ gerektirir [Serializable] . Di─čer eri┼čim seviyesi i├žin geni┼čletilebilir.

 public static void CopyTo( this object S, object T )
{
    foreach( var pS in S.GetType().GetProperties() )
    {
        foreach( var pT in T.GetType().GetProperties() )
        {
            if( pT.Name != pS.Name ) continue;
            ( pT.GetSetMethod() ).Invoke( T, new object[] 
            { pS.GetGetMethod().Invoke( S, null ) } );
        }
    };
}
 

40







Silverlight'ta ICloneable'─▒ kullanmada sorun ya┼č─▒yordum, ancak Seralizasyon fikrini sevdim, XML'i seralize edebilirim, bu y├╝zden ┼čunu yapt─▒m:

 static public class SerializeHelper
{
    //Michael White, Holly Springs Consulting, 2009
    //[email protected]
    public static T DeserializeXML<T>(string xmlData) where T:new()
    {
        if (string.IsNullOrEmpty(xmlData))
            return default(T);

        TextReader tr = new StringReader(xmlData);
        T DocItms = new T();
        XmlSerializer xms = new XmlSerializer(DocItms.GetType());
        DocItms = (T)xms.Deserialize(tr);

        return DocItms == null ? default(T) : DocItms;
    }

    public static string SeralizeObjectToXML<T>(T xmlObject)
    {
        StringBuilder sbTR = new StringBuilder();
        XmlSerializer xmsTR = new XmlSerializer(xmlObject.GetType());
        XmlWriterSettings xwsTR = new XmlWriterSettings();

        XmlWriter xmwTR = XmlWriter.Create(sbTR, xwsTR);
        xmsTR.Serialize(xmwTR,xmlObject);

        return sbTR.ToString();
    }

    public static T CloneObject<T>(T objClone) where T:new()
    {
        string GetString = SerializeHelper.SeralizeObjectToXML<T>(objClone);
        return SerializeHelper.DeserializeXML<T>(GetString);
    }
}
 

32







Az ├Ânce CloneExtensions k├╝t├╝phane projesi haz─▒rlad─▒m . ─░fade A─čac─▒ ├žal─▒┼čma zaman─▒ kod derlemesi taraf─▒ndan olu┼čturulan basit atama i┼člemlerini kullanarak h─▒zl─▒ ve derin klonlama ger├žekle┼čtirir.

Bu nas─▒l kullan─▒l─▒r?

Alanlar─▒n─▒z─▒ ve ├Âzelliklerinizi aras─▒na bir ton atayarak kendi y├Ântemlerinizi Clone veya Copy y├Ântemlerinizi yazmak yerine, ─░fade A─čac─▒ kullanarak program─▒n kendiniz i├žin yapmas─▒n─▒ sa─člay─▒n. GetClone<T>() Eklenti y├Ântemi olarak i┼čaretlenmi┼č y├Ântem, sadece ├Ârne─činizde aramak i├žin izin verir:

 var newInstance = source.GetClone();
 

Enum kullanmak source i├žin neyin kopyalanaca─č─▒n─▒ se├žebilirsiniz : newInstance CloningFlags

 var newInstance 
    = source.GetClone(CloningFlags.Properties | CloningFlags.CollectionItems);
 

Ne klonlanabilir?

  • ─░lkel (int, uint, byte, double, char vb.), Bilinen de─či┼čmez t├╝rleri (DateTime, TimeSpan, String) ve delegeler (Action, Func, vb.)
  • null
  • T [] dizileri
  • Genel s─▒n─▒flar ve yap─▒lar dahil, ├Âzel s─▒n─▒flar ve yap─▒lar.

A┼ča─č─▒daki s─▒n─▒f / yap─▒ ├╝yeleri dahili olarak klonlan─▒r:

  • Genel de─čerler, salt okunur alanlar
  • Hem olsun hem de ayarlanan eri┼čimcilerle birlikte genel m├╝lklerin de─čerleri
  • ICollection uygulayan t├╝rler i├žin koleksiyon ├Â─čeleri

Ne kadar h─▒zl─▒?

├ç├Âz├╝m, yans─▒madan daha h─▒zl─▒d─▒r, ├ž├╝nk├╝ ├╝yelerin bilgileri yaln─▒zca bir kez toplanmal─▒, daha ├Ânce GetClone<T> verilen t├╝r i├žin ilk kez kullan─▒lmal─▒d─▒r T .

Ayn─▒ t├╝rden birka├ž ├Ârne─či daha klonlad─▒─č─▒n─▒zda serile┼čtirme tabanl─▒ ├ž├Âz├╝mden de daha h─▒zl─▒d─▒r T .

ve dahas─▒...

Dok├╝mantasyonda ├╝retilen ifadeler hakk─▒nda daha fazla bilgi edinin .

┼×unun i├žin ├Ârnek ifade hata ay─▒klama listesi List<int> :

 .Lambda #Lambda1<System.Func`4[System.Collections.Generic.List`1[System.Int32],CloneExtensions.CloningFlags,System.Collections.Generic.IDictionary`2[System.Type,System.Func`2[System.Object,System.Object]],System.Collections.Generic.List`1[System.Int32]]>(
    System.Collections.Generic.List`1[System.Int32] $source,
    CloneExtensions.CloningFlags $flags,
    System.Collections.Generic.IDictionary`2[System.Type,System.Func`2[System.Object,System.Object]] $initializers) {
    .Block(System.Collections.Generic.List`1[System.Int32] $target) {
        .If ($source == null) {
            .Return #Label1 { null }
        } .Else {
            .Default(System.Void)
        };
        .If (
            .Call $initializers.ContainsKey(.Constant<System.Type>(System.Collections.Generic.List`1[System.Int32]))
        ) {
            $target = (System.Collections.Generic.List`1[System.Int32]).Call ($initializers.Item[.Constant<System.Type>(System.Collections.Generic.List`1[System.Int32])]
            ).Invoke((System.Object)$source)
        } .Else {
            $target = .New System.Collections.Generic.List`1[System.Int32]()
        };
        .If (
            ((System.Byte)$flags & (System.Byte).Constant<CloneExtensions.CloningFlags>(Fields)) == (System.Byte).Constant<CloneExtensions.CloningFlags>(Fields)
        ) {
            .Default(System.Void)
        } .Else {
            .Default(System.Void)
        };
        .If (
            ((System.Byte)$flags & (System.Byte).Constant<CloneExtensions.CloningFlags>(Properties)) == (System.Byte).Constant<CloneExtensions.CloningFlags>(Properties)
        ) {
            .Block() {
                $target.Capacity = .Call CloneExtensions.CloneFactory.GetClone(
                    $source.Capacity,
                    $flags,
                    $initializers)
            }
        } .Else {
            .Default(System.Void)
        };
        .If (
            ((System.Byte)$flags & (System.Byte).Constant<CloneExtensions.CloningFlags>(CollectionItems)) == (System.Byte).Constant<CloneExtensions.CloningFlags>(CollectionItems)
        ) {
            .Block(
                System.Collections.Generic.IEnumerator`1[System.Int32] $var1,
                System.Collections.Generic.ICollection`1[System.Int32] $var2) {
                $var1 = (System.Collections.Generic.IEnumerator`1[System.Int32]).Call $source.GetEnumerator();
                $var2 = (System.Collections.Generic.ICollection`1[System.Int32])$target;
                .Loop  {
                    .If (.Call $var1.MoveNext() != False) {
                        .Call $var2.Add(.Call CloneExtensions.CloneFactory.GetClone(
                                $var1.Current,
                                $flags,


                         $initializers))
                } .Else {
                    .Break #Label2 { }
                }
            }
            .LabelTarget #Label2:
        }
    } .Else {
        .Default(System.Void)
    };
    .Label
        $target
    .LabelTarget #Label1:
}
 

}

c # kodunu takip etmekle ayn─▒ anlam─▒ ta┼č─▒yanlar:

 (source, flags, initializers) =>
{
    if(source == null)
        return null;

    if(initializers.ContainsKey(typeof(List<int>))
        target = (List<int>)initializers[typeof(List<int>)].Invoke((object)source);
    else
        target = new List<int>();

    if((flags & CloningFlags.Properties) == CloningFlags.Properties)
    {
        target.Capacity = target.Capacity.GetClone(flags, initializers);
    }

    if((flags & CloningFlags.CollectionItems) == CloningFlags.CollectionItems)
    {
        var targetCollection = (ICollection<int>)target;
        foreach(var item in (ICollection<int>)source)
        {
            targetCollection.Add(item.Clone(flags, initializers));
        }
    }

    return target;
}
 

Kendi Clone y├Ântemini nas─▒l yazd─▒─č─▒na pek benzemiyor List<int> mu?


30







Zaten ValueInjecter veya Automapper gibi bir 3. parti uygulama kullan─▒yorsan─▒z , ┼čunun gibi bir ┼čey yapabilirsiniz:

 MyObject oldObj; // The existing object to clone

MyObject newObj = new MyObject();
newObj.InjectFrom(oldObj); // Using ValueInjecter syntax
 

Bu y├Ântemi kullanarak, nesnelerinize ISerializable veya ICloneable uygulamak zorunda de─čilsiniz. Bu, MVC / MVVM paterni ile ortakt─▒r, bu y├╝zden bunun gibi basit ara├žlar yarat─▒lm─▒┼čt─▒r.

bkz Codeplex ├╝zerinde valueinjecter derin klonlama ├ž├Âz├╝m├╝ .


27







En iyisi gibi bir uzatma y├Ântemi uygulamakt─▒r

 public static T DeepClone<T>(this T originalObject)
{ /* the cloning code */ }
 

ve ├ž├Âz├╝m├╝n herhangi bir yerinde kullan─▒n.

 var copy = anyObject.DeepClone();
 

A┼ča─č─▒daki ├╝├ž uygulamay─▒ yapabiliriz:

  1. Serile┼čtirme (en k─▒sa kod)
  2. Yans─▒ma ile - 5 kat daha h─▒zl─▒
  3. ─░fade A─ča├žlar─▒na G├Âre - 20 kat daha h─▒zl─▒

T├╝m ba─člant─▒l─▒ y├Ântemler iyi ├žal─▒┼č─▒yor ve derinlemesine test edildi.


21







K─▒sa cevap, ICloneable arabirimden miras alman─▒z ve ard─▒ndan .clone i┼člevini uygulaman─▒zd─▒r. Klon, ├╝ye olarak bir kopya yapmal─▒ ve onu gerektiren herhangi bir ├╝ye ├╝zerinde derin bir kopya yapmal─▒, ard─▒ndan ortaya ├ž─▒kan nesneyi d├Ând├╝rmelidir. Bu ├Âzyinelemeli bir i┼člemdir (klonlamak istedi─činiz s─▒n─▒f─▒n t├╝m ├╝yelerinin de─čer t├╝rleri veya ICloneable uygulamas─▒ ve ├╝yelerinin de─čer t├╝rleri veya ICloneable uygulamas─▒ vb. Olmas─▒n─▒ gerektirir).

ICloneable kullanarak klonlama hakk─▒nda daha ayr─▒nt─▒l─▒ bir a├ž─▒klama i├žin bu makaleye g├Âz at─▒n .

Uzun cevap ise "de─či┼čir" dir. Di─čerleri taraf─▒ndan belirtildi─či gibi, ICloneable jenerikler taraf─▒ndan desteklenmez, dairesel s─▒n─▒f referanslar─▒ i├žin ├Âzel hususlar gerektirir ve ger├žekte baz─▒lar─▒ taraf─▒ndan .NET Framework'te "hata" olarak g├Âr├╝l├╝r . Serile┼čtirme y├Ântemi nesnelerinizin serile┼čtirilebilir olmas─▒na ba─čl─▒d─▒r, bunlar olmayabilir ve ├╝zerinde kontrol sahibi olamayabilirsiniz. ├ťzerinde "en iyi" uygulama olan toplulukta hala ├žok fazla tart─▒┼čma var. Ger├žekte, ├ž├Âz├╝mlerin hi├žbiri ICloneable gibi ba┼člang─▒├žta oldu─ču gibi t├╝m durumlar i├žin en iyi uygulama tek beden uyan de─čildir.

Birka├ž se├ženek i├žin bu Geli┼čtiricinin K├Â┼česi makalesine bak─▒n (Ian'a te┼čekk├╝r ederiz).


21







  1. Temel olarak ICloneable aray├╝z├╝n├╝ uygulaman─▒z ve daha sonra nesne yap─▒s─▒ kopyalama i┼člemini ger├žekle┼čtirmeniz gerekir.
  2. T├╝m ├╝yelerin derin kopyas─▒ ise, t├╝m ├žocuklar─▒n da klonlanabilir oldu─čundan emin olman─▒z gerekir (se├žti─činiz ├ž├Âz├╝me ili┼čkin de─čildir).
  3. Bazen, bu i┼člem s─▒ras─▒nda baz─▒ k─▒s─▒tlamalar─▒n fark─▒nda olman─▒z gerekir; ├Ârne─čin, ORM nesnelerini kopyalarken ├žer├ževelerin ├žo─čunun yaln─▒zca bir nesnenin oturuma eklenmesine izin vermesi durumunda ve bu nesnenin klonlar─▒n─▒ YAPMAMANIZ durumunda veya m├╝mk├╝nse ├Âzen g├Âstermeniz gerekir. Bu nesnelerin oturumu ekleme hakk─▒nda.

┼×erefe.


17







EDIT: proje durduruldu

Bilinmeyen t├╝rlere ger├žek klonlama yapmak istiyorsan─▒z fastclone'a g├Âz atabilirsiniz .

Bu, ifadeye dayal─▒ klonlaman─▒n ikili serile┼čtirme i┼čleminden yakla┼č─▒k 10 kat daha h─▒zl─▒ ├žal─▒┼čmas─▒ ve tam nesne grafi─či b├╝t├╝nl├╝─č├╝n├╝ sa─člamas─▒d─▒r.

Bunun anlam─▒ ┼čudur: hiyerar┼činizdeki ayn─▒ nesneye birden ├žok kez ba┼čvurursan─▒z, klon ayr─▒ca referans verilen tek bir ├Ârnek ar─▒c─▒l─▒─č─▒na sahip olacakt─▒r.

Klonlanan nesnelerde aray├╝zlere, niteliklere veya ba┼čka herhangi bir de─či┼čikli─če gerek yoktur.


16







Her ┼čeyi basit tutun ve AutoMapper'─▒ di─čerlerinin dedi─či gibi kullan─▒n , bir nesneyi di─čerine e┼člemek basit bir k├╝t├╝phane ... Ayn─▒ nesneyle ayn─▒ nesneyi bir nesneye kopyalamak i├žin tek ihtiyac─▒n─▒z olan ├╝├ž kod sat─▒r─▒:

 MyType source = new MyType();
Mapper.CreateMap<MyType, MyType>();
MyType target = Mapper.Map<MyType, MyType>(source);
 

Hedef nesne ┼čimdi kaynak nesnenin bir kopyas─▒d─▒r. Yeterince basit de─čil mi? ├ç├Âz├╝m├╝n├╝zdeki her yerde kullanmak i├žin bir uzant─▒ y├Ântemi olu┼čturun:

 public static T Copy<T>(this T source)
{
    T copy = default(T);
    Mapper.CreateMap<T, T>();
    copy = Mapper.Map<T, T>(source);
    return copy;
}
 

Eklenti y├Ântemini kullanarak, ├╝├ž sat─▒r bir sat─▒r olur:

 MyType copy = source.Copy();
 

12







Bunu, <T> Listesini manuel olarak derin bir ┼čekilde kopyalamak zorunda olan bir .NET eksikli─činin ├╝stesinden gelmek i├žin geldim .

Bunu kullan─▒yorum:

 static public IEnumerable<SpotPlacement> CloneList(List<SpotPlacement> spotPlacements)
{
    foreach (SpotPlacement sp in spotPlacements)
    {
        yield return (SpotPlacement)sp.Clone();
    }
}
 

Ve ba┼čka bir yerde:

 public object Clone()
{
    OrderItem newOrderItem = new OrderItem();
    ...
    newOrderItem._exactPlacements.AddRange(SpotPlacement.CloneList(_exactPlacements));
    ...
    return newOrderItem;
}
 

Bunu yapan oneliner ile gelmeye ├žal─▒┼čt─▒m, ancak isimsiz y├Ântem bloklar─▒nda ├žal─▒┼čmad─▒─č─▒ i├žin verim m├╝mk├╝n de─čil.

Daha da iyisi, genel List <T> klonlay─▒c─▒ kullan─▒n:

 class Utility<T> where T : ICloneable
{
    static public IEnumerable<T> CloneList(List<T> tl)
    {
        foreach (T t in tl)
        {
            yield return (T)t.Clone();
        }
    }
}
 

11







S. Neden bu cevab─▒ se├žeyim?

  • .NET'in sahip olabilece─či en y├╝ksek h─▒zda istiyorsan─▒z, bu cevab─▒ se├žin.
  • Ger├žekten ama ger├žekten kolay bir klonlama y├Ântemi istiyorsan─▒z bu cevab─▒ yoksay─▒n.

Ba┼čka bir deyi┼čle, d├╝zeltilmesi gereken bir performans darbo─čaz─▒n─▒z yoksa ve bir profiler ile kan─▒tlayabilirsiniz .

Di─čer y├Ântemlerden 10 kat daha h─▒zl─▒

Derin bir klon ger├žekle┼čtirmenin a┼ča─č─▒daki y├Ântemi:

  • Serile┼čtirme / seri hale getirme i├žeren her ┼čeyden 10 kat daha h─▒zl─▒;
  • Olduk├ža lanet olas─▒ teorik maksimum h─▒za yak─▒n.

Ve y├Ântem ...

En y├╝ksek h─▒z i├žin, derin bir kopya yapmak i├žin Nested MemberwiseClone uygulamas─▒n─▒ kullanabilirsiniz . Neredeyse bir de─čer yap─▒s─▒n─▒ kopyalamakla ayn─▒ h─▒zdad─▒r ve (a) yans─▒ma veya (b) serile┼čtirme i┼čleminden (bu sayfadaki di─čer cevaplarda a├ž─▒kland─▒─č─▒ gibi) ├žok daha h─▒zl─▒d─▒r.

O Not e─čer kulland─▒─č─▒n─▒z derin kopya i├žin ─░├ži├že MemberwiseClone , el s─▒n─▒ftaki her i├ž i├že d├╝zeyde ve t├╝m basitkopyas─▒n─▒ y├Ântemleri tam bir klon olu┼čturmak i├žin ad─▒ ge├žen ├ža─č─▒ran bir deepcopy i├žin basitkopyas─▒n─▒ uygulamak zorunda. Bu basittir: toplamda sadece birka├ž sat─▒r vard─▒r, a┼ča─č─▒daki demo koduna bak─▒n.

─░┼čte 100.000 klonun nispi performans fark─▒n─▒ g├Âsteren kodun ├ž─▒kt─▒s─▒:

  • Yuvalanm─▒┼č yap─▒larda Nested MemberwiseClone i├žin 1.08 saniye
  • Yuvalanm─▒┼č s─▒n─▒flardaki Yuvalanm─▒┼č MemberwiseClone i├žin 4.77 saniye
  • Serile┼čtirme / Serile┼čtirme i├žin 39.93 saniye

Nested MemberwiseClone bir s─▒n─▒fta bir yap─▒y─▒ kopyalamak kadar h─▒zl─▒ ve bir yap─▒y─▒ kopyalamak, .NET'in yapabilece─či teorik maksimum h─▒za olduk├ža yak─▒n.

 Demo 1 of shallow and deep copy, using classes and MemberwiseClone:
  Create Bob
    Bob.Age=30, Bob.Purchase.Description=Lamborghini
  Clone Bob >> BobsSon
  Adjust BobsSon details
    BobsSon.Age=2, BobsSon.Purchase.Description=Toy car
  Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:
    Bob.Age=30, Bob.Purchase.Description=Lamborghini
  Elapsed time: 00:00:04.7795670,30000000

Demo 2 of shallow and deep copy, using structs and value copying:
  Create Bob
    Bob.Age=30, Bob.Purchase.Description=Lamborghini
  Clone Bob >> BobsSon
  Adjust BobsSon details:
    BobsSon.Age=2, BobsSon.Purchase.Description=Toy car
  Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:
    Bob.Age=30, Bob.Purchase.Description=Lamborghini
  Elapsed time: 00:00:01.0875454,30000000

Demo 3 of deep copy, using class and serialize/deserialize:
  Elapsed time: 00:00:39.9339425,30000000
 

MemberwiseCopy kullanarak derin bir kopyan─▒n nas─▒l yap─▒laca─č─▒n─▒ anlamak i├žin, yukar─▒daki zamanlar─▒ olu┼čturmak i├žin kullan─▒lan demo proje:

 // Nested MemberwiseClone example. 
// Added to demo how to deep copy a reference class.
[Serializable] // Not required if using MemberwiseClone, only used for speed comparison using serialization.
public class Person
{
    public Person(int age, string description)
    {
        this.Age = age;
        this.Purchase.Description = description;
    }
    [Serializable] // Not required if using MemberwiseClone
    public class PurchaseType
    {
        public string Description;
        public PurchaseType ShallowCopy()
        {
            return (PurchaseType)this.MemberwiseClone();
        }
    }
    public PurchaseType Purchase = new PurchaseType();
    public int Age;
    // Add this if using nested MemberwiseClone.
    // This is a class, which is a reference type, so cloning is more difficult.
    public Person ShallowCopy()
    {
        return (Person)this.MemberwiseClone();
    }
    // Add this if using nested MemberwiseClone.
    // This is a class, which is a reference type, so cloning is more difficult.
    public Person DeepCopy()
    {
            // Clone the root ...
        Person other = (Person) this.MemberwiseClone();
            // ... then clone the nested class.
        other.Purchase = this.Purchase.ShallowCopy();
        return other;
    }
}
// Added to demo how to copy a value struct (this is easy - a deep copy happens by default)
public struct PersonStruct
{
    public PersonStruct(int age, string description)
    {
        this.Age = age;
        this.Purchase.Description = description;
    }
    public struct PurchaseType
    {
        public string Description;
    }
    public PurchaseType Purchase;
    public int Age;
    // This is a struct, which is a value type, so everything is a clone by default.
    public PersonStruct ShallowCopy()
    {
        return (PersonStruct)this;
    }
    // This is a struct, which is a value type, so everything is a clone by default.
    public PersonStruct DeepCopy()
    {
        return (PersonStruct)this;
    }
}
// Added only for a speed comparison.
public class MyDeepCopy
{
    public static T DeepCopy<T>(T obj)
    {
        object result = null;
        using (var ms = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(ms, obj);
            ms.Position = 0;
            result = (T)formatter.Deserialize(ms);
            ms.Close();
        }
        return (T)result;
    }
}
 

Ard─▒ndan demosu ana telefondan aray─▒n:

 void MyMain(string[] args)
{
    {
        Console.Write("Demo 1 of shallow and deep copy, using classes and MemberwiseCopy:\n");
        var Bob = new Person(30, "Lamborghini");
        Console.Write("  Create Bob\n");
        Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
        Console.Write("  Clone Bob >> BobsSon\n");
        var BobsSon = Bob.DeepCopy();
        Console.Write("  Adjust BobsSon details\n");
        BobsSon.Age = 2;
        BobsSon.Purchase.Description = "Toy car";
        Console.Write("    BobsSon.Age={0}, BobsSon.Purchase.Description={1}\n", BobsSon.Age, BobsSon.Purchase.Description);
        Console.Write("  Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:\n");
        Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
        Debug.Assert(Bob.Age == 30);
        Debug.Assert(Bob.Purchase.Description == "Lamborghini");
        var sw = new Stopwatch();
        sw.Start();
        int total = 0;
        for (int i = 0; i < 100000; i++)
        {
            var n = Bob.DeepCopy();
            total += n.Age;
        }
        Console.Write("  Elapsed time: {0},{1}\n\n", sw.Elapsed, total);
    }
    {               
        Console.Write("Demo 2 of shallow and deep copy, using structs:\n");
        var Bob = new PersonStruct(30, "Lamborghini");
        Console.Write("  Create Bob\n");
        Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
        Console.Write("  Clone Bob >> BobsSon\n");
        var BobsSon = Bob.DeepCopy();
        Console.Write("  Adjust BobsSon details:\n");
        BobsSon.Age = 2;
        BobsSon.Purchase.Description = "Toy car";
        Console.Write("    BobsSon.Age={0}, BobsSon.Purchase.Description={1}\n", BobsSon.Age, BobsSon.Purchase.Description);
        Console.Write("  Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:\n");
        Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);                
        Debug.Assert(Bob.Age == 30);
        Debug.Assert(Bob.Purchase.Description == "Lamborghini");
        var sw = new Stopwatch();
        sw.Start();
        int total = 0;
        for (int i = 0; i < 100000; i++)
        {
            var n = Bob.DeepCopy();
            total += n.Age;
        }
        Console.Write("  Elapsed time: {0},{1}\n\n", sw.Elapsed, total);
    }
    {
        Console.Write("Demo 3 of deep copy, using class and serialize/deserialize:\n");
        int total = 0;
        var sw = new Stopwatch();
        sw.Start();
        var Bob = new Person(30, "Lamborghini");
        for (int i = 0; i < 100000; i++)
        {
            var BobsSon = MyDeepCopy.DeepCopy<Person>(Bob);
            total += BobsSon.Age;
        }
        Console.Write("  Elapsed time: {0},{1}\n", sw.Elapsed, total);
    }
    Console.ReadKey();
}
 

Yine, bu not e─čer kulland─▒─č─▒n─▒z derin kopya i├žin ─░├ži├že MemberwiseClone , sahip manuel s─▒n─▒ftaki her i├ž i├že d├╝zeyde ve t├╝m basitkopyas─▒n─▒ y├Ântemleri tam bir klon olu┼čturmak i├žin ad─▒ ge├žen ├ža─č─▒ran bir deepcopy i├žin basitkopyas─▒n─▒ uygulamakt─▒r. Bu basittir: toplamda sadece birka├ž sat─▒r vard─▒r, yukar─▒daki demo koduna bak─▒n.

De─čer t├╝rleri ve Referans T├╝rleri

Bir nesneyi klonlamak s├Âz konusu oldu─čunda, " yap─▒ " ile " s─▒n─▒f " aras─▒nda b├╝y├╝k bir fark oldu─čunu unutmay─▒n :

  • E─čer bir " yap─▒ " ya sahipseniz, bu sadece bir de─čer kopyalayabilmeniz i├žin bir de─čer t├╝r├╝d├╝r ve i├žerikler klonlan─▒r (ancak bu yaz─▒daki teknikleri kullanmazsan─▒z sadece s─▒─č bir klon yapar).
  • Bir " s─▒n─▒f─▒n─▒z " varsa, bu bir referans t├╝r├╝d├╝r , bu nedenle kopyalarsan─▒z, yapt─▒─č─▒n─▒z tek ┼čey imleci kopyalamakt─▒r. Ger├žek bir klon olu┼čturmak i├žin daha yarat─▒c─▒ olman─▒z ve bellekteki orijinal nesnenin ba┼čka bir kopyas─▒n─▒ olu┼čturan de─čer t├╝rleri ve referans t├╝rleri aras─▒ndaki farklar─▒ kullanman─▒z gerekir .

De─čer t├╝rleri ve referans t├╝rleri aras─▒ndaki farklar─▒ g├Âr├╝n .

Hata ay─▒klamada yard─▒mc─▒ olmak i├žin sa─člama toplam─▒

  • Nesneleri yanl─▒┼č ┼čekilde klonlamak, s─▒k─▒┼čmas─▒ zor hatalara yol a├žabilir. ├ťretim kodunda, nesnenin do─čru ┼čekilde klonland─▒─č─▒n─▒ ve ba┼čka bir referans taraf─▒ndan bozulmad─▒─č─▒n─▒ kontrol etmek i├žin bir sa─člama toplam─▒ uygulama e─čilimindeyim. Bu sa─člama toplam─▒ Serbest B─▒rakma modunda kapat─▒labilir.
  • Bu y├Ântemi olduk├ža faydal─▒ buluyorum: genellikle, her ┼čeyi de─čil, yaln─▒zca nesnenin b├Âl├╝mlerini klonlamak istersiniz.

Di─čer bir├žok ba┼čl─▒ktan bir├žok par├žay─▒ ay─▒rmak i├žin ger├žekten yararl─▒

Bu kod i├žin m├╝kemmel bir kullan─▒m ├Ârne─či, ├╝retici / t├╝ketici modelini uygulamak i├žin i├ž i├že bir s─▒n─▒f veya yap─▒ klonlar─▒n─▒ bir kuyru─ča beslemektir.

  • Sahip olduklar─▒ bir s─▒n─▒f─▒ de─či┼čtiren ve ard─▒ndan bu s─▒n─▒f─▒n tam bir kopyas─▒n─▒ a'ya yerle┼čtiren bir (veya daha fazla) i┼č par├žac─▒─č─▒m─▒z olabilir ConcurrentQueue .
  • Daha sonra, bu s─▒n─▒flar─▒n kopyalar─▒n─▒ ├žekip bunlarla ilgilenen bir (veya daha fazla) i┼č par├žac─▒─č─▒m─▒z var.

Bu pratikte son derece iyi ├žal─▒┼č─▒r ve bir veya daha fazla say─▒da iplikten (t├╝keticiler) bir├žok ipli─či (├╝reticiler) ay─▒rmam─▒za izin verir.

Ve bu y├Ântem de g├Âzle g├Âr├╝l├╝r derecede h─▒zl─▒: i├ž i├že ge├žmi┼č yap─▒lar kullan─▒rsak, i├ž i├že ge├žmi┼č s─▒n─▒flar─▒ serile┼čtirme / seri hale getirme i┼čleminden 35 kat daha h─▒zl─▒d─▒r ve makinede bulunan t├╝m i┼č par├žac─▒klar─▒ndan yararlanmam─▒z─▒ sa─člar.

G├╝ncelle┼čtirme

Anla┼č─▒lan ExpressMapper, daha h─▒zl─▒ de─čilse de yukar─▒daki gibi elle kodlamaktan daha h─▒zl─▒. Bir profilciyle nas─▒l kar┼č─▒la┼čt─▒r─▒ld─▒klar─▒n─▒ g├Ârmem gerekebilir.


9







Genel olarak, ICloneable arabirimini uygular ve Clone'u kendiniz uygulars─▒n─▒z. C # nesneleri, t├╝m ilkeller i├žin size yard─▒mc─▒ olabilecek s─▒─č bir kopya ger├žekle┼čtiren yerle┼čik bir MemberwiseClone y├Ântemine sahiptir.

Derin bir kopya i├žin, otomatik olarak nas─▒l yap─▒laca─č─▒n─▒ bilemez.


8







Bunun yans─▒ma yoluyla da uyguland─▒─č─▒n─▒ g├Ârd├╝m. Temel olarak, bir nesnenin ├╝yeleri aras─▒nda yinelenen ve uygun ┼čekilde onlar─▒ yeni nesneye kopyalayacak bir y├Ântem vard─▒. Referans t├╝rlerine veya koleksiyonlar─▒na ula┼čt─▒─č─▒nda, kendisine ├Âzyinelemeli bir ├ža─čr─▒ yapt─▒─č─▒n─▒ d├╝┼č├╝n├╝yorum. Yans─▒ma pahal─▒d─▒r, ancak olduk├ža iyi ├žal─▒┼čt─▒.


8







─░┼čte derin bir kopya uygulamas─▒:

 public static object CloneObject(object opSource)
{
    //grab the type and create a new instance of that type
    Type opSourceType = opSource.GetType();
    object opTarget = CreateInstanceOfType(opSourceType);

    //grab the properties
    PropertyInfo[] opPropertyInfo = opSourceType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

    //iterate over the properties and if it has a 'set' method assign it from the source TO the target
    foreach (PropertyInfo item in opPropertyInfo)
    {
        if (item.CanWrite)
        {
            //value types can simply be 'set'
            if (item.PropertyType.IsValueType || item.PropertyType.IsEnum || item.PropertyType.Equals(typeof(System.String)))
            {
                item.SetValue(opTarget, item.GetValue(opSource, null), null);
            }
            //object/complex types need to recursively call this method until the end of the tree is reached
            else
            {
                object opPropertyValue = item.GetValue(opSource, null);
                if (opPropertyValue == null)
                {
                    item.SetValue(opTarget, null, null);
                }
                else
                {
                    item.SetValue(opTarget, CloneObject(opPropertyValue), null);
                }
            }
        }
    }
    //return the new item
    return opTarget;
}
 

8







Farkl─▒ projelerdeki t├╝m gereksinimlerimi kar┼č─▒layan bir klonlay─▒c─▒ bulamad─▒─č─▒m i├žin, kodumu klon gereksinimlerini kar┼č─▒layacak ┼čekilde uyarlamak yerine, farkl─▒ kod yap─▒lar─▒na uyarlanabilen ve uyarlanabilen derin bir klon olu┼čturdum. Klonlanacak koda ek a├ž─▒klamalar ekleyerek elde edilir veya varsay─▒lan davran─▒┼ča sahip oldu─čunuz gibi kodu b─▒rakman─▒z yeterlidir. Yans─▒ma, ├Ânbellek t├╝r├╝n├╝ kullan─▒r ve fasterflect'e dayan─▒r . Klonlama i┼člemi ├žok fazla veri ve y├╝ksek nesne hiyerar┼čisi i├žin ├žok h─▒zl─▒d─▒r (di─čer yans─▒ma / serile┼čtirme tabanl─▒ algoritmalara k─▒yasla).

https://github.com/kalisohn/CloneBehave

Bir nuget paketi olarak da mevcuttur: https://www.nuget.org/packages/Clone.Behave/1.0.0

├ľrne─čin: A┼ča─č─▒daki kod Adres Adresini derinden koyacakt─▒r, ancak yaln─▒zca _currentJob alan─▒n─▒n s─▒─č bir kopyas─▒n─▒ ger├žekle┼čtirir.

 public class Person 
{
  [DeepClone(DeepCloneBehavior.Shallow)]
  private Job _currentJob;      

  public string Name { get; set; }

  public Job CurrentJob 
  { 
    get{ return _currentJob; }
    set{ _currentJob = value; }
  }

  public Person Manager { get; set; }
}

public class Address 
{      
  public Person PersonLivingHere { get; set; }
}

Address adr = new Address();
adr.PersonLivingHere = new Person("John");
adr.PersonLivingHere.BestFriend = new Person("James");
adr.PersonLivingHere.CurrentJob = new Job("Programmer");

Address adrClone = adr.Clone();

//RESULT
adr.PersonLivingHere == adrClone.PersonLivingHere //false
adr.PersonLivingHere.Manager == adrClone.PersonLivingHere.Manager //false
adr.PersonLivingHere.CurrentJob == adrClone.PersonLivingHere.CurrentJob //true
adr.PersonLivingHere.CurrentJob.AnyProperty == adrClone.PersonLivingHere.CurrentJob.AnyProperty //true
 

8







Bu y├Ântem benim i├žin sorunu ├ž├Âzd├╝:

 private static MyObj DeepCopy(MyObj source)
        {

            var DeserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };

            return JsonConvert.DeserializeObject<MyObj >(JsonConvert.SerializeObject(source), DeserializeSettings);

        }
 

Bu ┼čekilde kullan─▒n: MyObj a = DeepCopy(b);


7







Copyconstructors'─▒ ┼č├Âyle seviyorum:

     public AnyObject(AnyObject anyObject)
    {
        foreach (var property in typeof(AnyObject).GetProperties())
        {
            property.SetValue(this, property.GetValue(anyObject));
        }
        foreach (var field in typeof(AnyObject).GetFields())
        {
            field.SetValue(this, field.GetValue(anyObject));
        }
    }
 

Kopyalanacak ba┼čka ┼čeyler varsa ekleyin


6







Kod ├╝reteci

Serile┼čtirme i┼čleminden manuel uygulamaya ge├ži┼čten yans─▒maya kadar bir├žok fikir g├Ârd├╝k ve CGbR Code Generator'─▒ kullanarak tamamen farkl─▒ bir yakla┼č─▒m ├Ânermek istiyorum . Olu┼čturma klonlama y├Ântemi bellek ve CPU a├ž─▒s─▒ndan verimlidir ve standart DataContractSerializer'dan 300 kat daha h─▒zl─▒d─▒r.

─░htiyac─▒n─▒z olan tek ┼čey k─▒smi bir s─▒n─▒f tan─▒m─▒ ICloneable ve jenerat├Âr gerisini halleder:

 public partial class Root : ICloneable
{
    public Root(int number)
    {
        _number = number;
    }
    private int _number;

    public Partial[] Partials { get; set; }

    public IList<ulong> Numbers { get; set; }

    public object Clone()
    {
        return Clone(true);
    }

    private Root()
    {
    }
} 

public partial class Root
{
    public Root Clone(bool deep)
    {
        var copy = new Root();
        // All value types can be simply copied
        copy._number = _number; 
        if (deep)
        {
            // In a deep clone the references are cloned 
            var tempPartials = new Partial[Partials.Length];
            for (var i = 0; i < Partials.Length; i++)
            {
                var value = Partials[i];
                value = value.Clone(true);
                tempPartials[i] = value;
            }
            copy.Partials = tempPartials;
            var tempNumbers = new List<ulong>(Numbers.Count);
            for (var i = 0; i < Numbers.Count; i++)
            {
                var value = Numbers[i];
                tempNumbers.Add(value);
            }
            copy.Numbers = tempNumbers;
        }
        else
        {
            // In a shallow clone only references are copied
            copy.Partials = Partials; 
            copy.Numbers = Numbers; 
        }
        return copy;
    }
}
 

Not: En son s├╝r├╝mde daha fazla kontrol var, ancak daha iyi anla┼č─▒lmas─▒ i├žin onlar─▒ d─▒┼čar─▒da b─▒rakt─▒m.


6







─░┼čte benim i├žin seri hale getirme / seri hale getirme i┼člemine ba┼člamadan h─▒zl─▒ ve kolay bir ├ž├Âz├╝m.

 public class MyClass
{
    public virtual MyClass DeepClone()
    {
        var returnObj = (MyClass)MemberwiseClone();
        var type = returnObj.GetType();
        var fieldInfoArray = type.GetRuntimeFields().ToArray();

        foreach (var fieldInfo in fieldInfoArray)
        {
            object sourceFieldValue = fieldInfo.GetValue(this);
            if (!(sourceFieldValue is MyClass))
            {
                continue;
            }

            var sourceObj = (MyClass)sourceFieldValue;
            var clonedObj = sourceObj.DeepClone();
            fieldInfo.SetValue(returnObj, clonedObj);
        }
        return returnObj;
    }
}
 

EDIT : gerektirir

     using System.Linq;
    using System.Reflection;
 

Ben b├Âyle kulland─▒m

 public MyClass Clone(MyClass theObjectIneededToClone)
{
    MyClass clonedObj = theObjectIneededToClone.DeepClone();
}
 

6







Bunu deneyebilece─čini d├╝┼č├╝n├╝yorum.

 MyObject myObj = GetMyObj(); // Create and fill a new object
MyObject newObj = new MyObject(myObj); //DeepClone it
 

6







Bu ad─▒mlar─▒ takip et:

  • D├Ând├╝ren ve t├╝retilen ve bir y├Ântem i├žeren ISelf<T> salt okunur bir Self ├Âzellik olan bir tan─▒mlay─▒n . T ICloneable<out T> ISelf<T> T Clone()
  • Ard─▒ndan , iletilen t├╝re CloneBase bir protected virtual generic VirtualClone d├Âk├╝m uygulayan bir t├╝r tan─▒mlay─▒n MemberwiseClone .
  • Her t├╝retilmi┼č t├╝r VirtualClone , temel klonlama y├Ântemini ├ža─č─▒rarak ve daha sonra, VirtualClone y├Ânteminin hen├╝z i┼čleme koymad─▒─č─▒ t├╝retilmi┼č t├╝r├╝n bu y├Ânlerini d├╝zg├╝n bir ┼čekilde klonlamak i├žin yap─▒lmas─▒ gerekenleri yaparak uygulamal─▒d─▒r.

En y├╝ksek kal─▒t─▒m ├žok y├Ânl├╝l├╝─č├╝ i├žin, kamu klonlama i┼člevselli─čini ortaya ├ž─▒karan s─▒n─▒flar sealed , klonlama eksikli─či d─▒┼č─▒nda ayn─▒ olan temel bir s─▒n─▒ftan t├╝retilmelidir. A├ž─▒k klonlanabilir t├╝r├╝n de─či┼čkenlerini ge├žmek yerine, t├╝r├╝n bir parametresini al─▒n ICloneable<theNonCloneableType> . Bu, klonlanabilir bir t├╝revinin klonlanabilir bir t├╝rev Foo ile ├žal─▒┼čmas─▒n─▒ bekleyen DerivedFoo , fakat ayn─▒ zamanda klonlanamayan t├╝revlerin olu┼čturulmas─▒na izin veren bir rutine izin verecektir Foo .


5







'[Seri hale getirilebilir]' ve '[DataContract]' ile ├žal─▒┼čan kabul edilen yan─▒t─▒n bir s├╝r├╝m├╝n├╝ olu┼čturdum. Yazd─▒─č─▒mdan bu yana bir s├╝re ge├žti, ama do─čru hat─▒rl─▒yorsam [DataContract] farkl─▒ bir serile┼čtiriciye ihtiya├ž duyuyordu.

Gerektiren Sistem, System.IO, System.Runtime.Serialization, System.Runtime.Serialization.Formatters.Binary, System.Xml ;

 public static class ObjectCopier
{

    /// <summary>
    /// Perform a deep Copy of an object that is marked with '[Serializable]' or '[DataContract]'
    /// </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 Clone<T>(T source)
    {
        if (typeof(T).IsSerializable == true)
        {
            return CloneUsingSerializable<T>(source);
        }

        if (IsDataContract(typeof(T)) == true)
        {
            return CloneUsingDataContracts<T>(source);
        }

        throw new ArgumentException("The type must be Serializable or use DataContracts.", "source");
    }


    /// <summary>
    /// Perform a deep Copy of an object that is marked with '[Serializable]'
    /// </summary>
    /// <remarks>
    /// Found on http://stackoverflow.com/questions/78536/cloning-objects-in-c-sharp
    /// Uses code found on CodeProject, which allows free use in third party apps
    /// - http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
    /// </remarks>
    /// <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 CloneUsingSerializable<T>(T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", "source");
        }

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

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


    /// <summary>
    /// Perform a deep Copy of an object that is marked with '[DataContract]'
    /// </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 CloneUsingDataContracts<T>(T source)
    {
        if (IsDataContract(typeof(T)) == false)
        {
            throw new ArgumentException("The type must be a data contract.", "source");
        }

        // ** Don't serialize a null object, simply return the default for that object
        if (Object.ReferenceEquals(source, null))
        {
            return default(T);
        }

        DataContractSerializer dcs = new DataContractSerializer(typeof(T));
        using(Stream stream = new MemoryStream())
        {
            using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(stream))
            {
                dcs.WriteObject(writer, source);
                writer.Flush();
                stream.Seek(0, SeekOrigin.Begin);
                using (XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
                {
                    return (T)dcs.ReadObject(reader);
                }
            }
        }
    }


    /// <summary>
    /// Helper function to check if a class is a [DataContract]
    /// </summary>
    /// <param name="type">The type of the object to check.</param>
    /// <returns>Boolean flag indicating if the class is a DataContract (true) or not (false) </returns>
    public static bool IsDataContract(Type type)
    {
        object[] attributes = type.GetCustomAttributes(typeof(DataContractAttribute), false);
        return attributes.Length == 1;
    }

} 
 

4







S─▒n─▒f nesnenizi klonlamak i├žin Object.MemberwiseClone y├Ântemini kullanabilirsiniz,

sadece bu fonksiyonu s─▒n─▒f─▒n─▒za ekleyin:

 public class yourClass
{
    // ...
    // ...

    public yourClass DeepCopy()
    {
        yourClass othercopy = (yourClass)this.MemberwiseClone();
        return othercopy;
    }
}
 

sonra derinlemesine ba─č─▒ms─▒z bir kopya yapmak i├žin sadece DeepCopy y├Ântemini ├ža─č─▒r─▒n:

 yourClass newLine = oldLine.DeepCopy();
 

Bu yard─▒mc─▒ olur umar─▒m.


4







Tamam, bu yaz─▒daki yans─▒malar─▒n baz─▒ a├ž─▒k ├Ârnekleri var, ancak onu do─čru ┼čekilde ├Ânbelle─če almaya ba┼člayana kadar BUT yans─▒mas─▒ genellikle yava┼čt─▒r.

D├╝zg├╝n bir ┼čekilde ├Ânbelle─če al─▒rsan─▒z, 1000000 nesnesini 4,6 s (Kep├že taraf─▒ndan ├Âl├ž├╝len) kadar derin klonlar.

 static readonly Dictionary<Type, PropertyInfo[]> ProperyList = new Dictionary<Type, PropertyInfo[]>();
 

├Ânbelle─če al─▒nm─▒┼č ├Âzellikleri alman─▒z veya s├Âzl├╝─če yeni eklemeniz ve bunlar─▒ basit├že kullanman─▒z

 foreach (var prop in propList)
{
        var value = prop.GetValue(source, null);   
        prop.SetValue(copyInstance, value, null);
}
 

tam kod, g├Ânderimimi ba┼čka bir cevapta kontrol et

https://stackoverflow.com/a/34365709/4711853


4







Nesne A─čac─▒n─▒z S─▒ralanabilirse, bunun gibi bir ┼čey de kullanabilirsiniz

 static public MyClass Clone(MyClass myClass)
{
    MyClass clone;
    XmlSerializer ser = new XmlSerializer(typeof(MyClass), _xmlAttributeOverrides);
    using (var ms = new MemoryStream())
    {
        ser.Serialize(ms, myClass);
        ms.Position = 0;
        clone = (MyClass)ser.Deserialize(ms);
    }
    return clone;
}
 

bu ├ç├Âz├╝m├╝n olduk├ža kolay oldu─ču ancak di─čer ├ž├Âz├╝mlerin olabilece─či kadar performans g├Âstermedi─či konusunda bilgi sahibi olun.

Ve e─čer S─▒n─▒f b├╝y├╝rse, sadece serile┼čtirilmi┼č olan klonlanm─▒┼č alanlar─▒n olaca─č─▒ndan emin olun.


4