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
copy = (t) formatter.deserialize(stream);
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
Post a Comment