c# - Object deep clone implementation -


i have implement generic extention deepclone method can used reference type instance deep copy. implement following

static class classcopy {     static public t deepclone<t> (this t instance)     {         if (instance == null) return null;         var type = instance.gettype();         t copy;         var flags = bindingflags.flattenhierarchy | bindingflags.public | bindingflags.nonpublic |                     bindingflags.instance;          var fields = type.getfields(flags);          // if type serializable - create instance copy using binaryformatter         if (type.isserializable)         {             using (var stream = new memorystream())             {                 var formatter = new binaryformatter();                 formatter.serialize(stream, instance);                 stream.position = 0;                 copy = (t) formatter.deserialize(stream);             }              // copy fiels  not marked serializable              foreach (var field in fields)             {                 if (!field.isnotserialized) continue;                 var value = field.getvalue(instance);                  //recursion!!!                 //for each embedded object create deep copy                 value = value != null  ? value.deepclone() : value;                 field.setvalue(copy, value);             }         }         else         {             // if type not serializable - create instance copy using activator             //(if there default constructor)             // or formatterservices ( if there no constractor)              copy = createinstance<t>(type);             foreach (var field in fields)             {                 var value = field.getvalue(instance);                  //recursion!!!                 value = value != null  ? value.deepclone() : value;                 field.setvalue(copy, value);             }         }          //copy properties          //in order copy backing fields  auto-implemented properties          var properties = type.getproperties(flags|bindingflags.setproperty);         foreach (var property in properties)         {             if (property.canwrite)             {                 var value = property.getvalue(instance);                  //recursion!!!                 value = value != null ? value.deepclone() : null;                 property.setvalue(copy, value);             }         }         return copy;     }      private static t createinstance<t>(type t) t: class     {         t instance;         var constructor = t.getconstructor(type.emptytypes);         if (constructor != null)         {             instance = activator.createinstance(t) t;             return instance;         }         instance = formatterservices.getuninitializedobject(t) t;         return instance;     } } 

it works well. if object cloned , reference type fields have mutual references code leads infinite loops. e.g.

private static void main(string[] args) {     var parent = new parent();     parent.child = new child();     parent.child.parent = parent;     //infinite loop!!!     var parent1 = parent.deepclone(); }  class parent {     public child child { get; set; } } class child {     public parent parent { get; set; } } 

does has idea how implement task? should implemented literally , no variations allowed (it's practicum). lot tips!

what can pass around dictionary of items mapped clones. method this:

static private t deepclone<t> (this t instance, idictionary<object, object> originaltoalreadycloned) t: class

now first thing after if (instance == null) return null;, check if instance present in originaltoalreadycloned , if so, return it.

in order populate it, after

  1. copy = (t) formatter.deserialize(stream);
  2. copy = createinstance<t>(type);

call originaltoalreadycloned.add(instance, copy);

finally, provide new top-level method:

static private t deepclone<t> (this t instance) t: class calls deepclone(instance, new dictionary<object, object>());

by way, value = value != null && value.gettype().isclass? value.deepclone() : null; seems wrong. you're saying is, if value not class, set null. if it's not class, can't set null. i'm not sure why don't clone these items too, , why deepclone restricted classes.


Comments

Popular posts from this blog

python - Subclassed QStyledItemDelegate ignores Stylesheet -

java - HttpClient 3.1 Connection pooling vs HttpClient 4.3.2 -

SQL: Divide the sum of values in one table with the count of rows in another -