how can I deep clone an instance of any object?

how can I deep clone an instance of an object

for example: i want to clone an instance of the control class TabPage,including the references to its member.If I got the clone of the TabPage class,I can add it to any TabPlane i want with the same design.

any ideas




Answer this question

how can I deep clone an instance of any object?

  • Luciano Bargmann

    You can also serialize your object to a memorystream, and then deserialize it. You then have a copy (clone) of your object as well.
    (You can implement this in the Clone() method of your object; however, you must make sure that your object is serializeable)


  • Monsky

    I hope this is readable, since i can't seem to find the option to post my code snippet in a descent manner.

    These two methods can be used to clone many objects. Unfortunatly cloning controls doesn't work. This is probably due to the same reasons why controls can't be serialized, they are just hooked in too much with the operating system.

    What you can do with these methods however is tweak them so that only certain data is copied. You don't need all the data from the object anyway. There is however still a problem with arrays and the like, but i didn't have the time for that atm. I hope you have at least an idea of the possibilities. (also you can see that this code is not going to be fast)

    public object CloneObject(object source)
    {
    Type sourceType = source.GetType();

    // First make an instance of the type of the source object.
    object target = CreateInstanceOfType(sourceType);

    // Get a list of all the fields of the type.
    PropertyInfo[] fields = sourceType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

    // Iterate through all the fields getting the value from the source, and setting them on the target.
    foreach (PropertyInfo fi in fields)
    {
    if (fi.CanWrite)
    {
    // If the type of the field is a value type, an enumeration, or a string,
    // we can suffice by just setting the value.
    if (fi.PropertyType.IsValueType || fi.PropertyType.IsEnum || fi.PropertyType.Equals(typeof(System.String)))
    fi.SetValue(target, fi.GetValue(source, null), null);

    // If the type of the field is a complex type
    // we need to call clone object to clone it as well.
    else
    {
    object value = fi.GetValue(source, null);
    if (value == null)
    fi.SetValue(target, null, null);
    else
    fi.SetValue(target, CloneObject(value), null);
    }
    }
    }

    return target;
    }

    public object CreateInstanceOfType(Type type)
    {
    // First make an instance of the type.
    object instance = null;

    // If there is an empty constructor, call that.
    if (type.GetConstructor(Type.EmptyTypes) != null)
    instance = Activator.CreateInstance(type);
    else
    {
    // Otherwise get the first available constructor and fill in some default values.
    // (we are trying to set all properties anyway so it shouldn't be much of a problem).
    ConstructorInfo ci = type.GetConstructors()[0];
    ParameterInfo[] parameters = ci.GetParameters();

    object[] ciParams = new object[parameters.Length];

    for (int i = 0; i < parameters.Length; i++)
    {
    if (parameters[ i ].DefaultValue != null)
    {
    ciParams[ i ] = parameters[ i ].DefaultValue;
    continue;
    }

    Type paramType = parameters[ i ].ParameterType;
    ciParams[ i ] = CreateInstanceOfType(paramType);
    }

    instance = ci.Invoke(ciParams);
    }

    return instance;
    }


  • guarriman

    thank you ....

    I got your idea.



  • Tim Landgrave

    It's a tough work,isn't it

    the controls are not marked as serializable,I can't use that way;

    could you give me your code sample,that'll be very kind of you.



  • __SAW___

    All the above works alright, but ... the other question arising from this chain is how to clone the object with events handlers I'd also appreciate if anyone has an idea on how to implement this in cf net 2.0

    Thanks


  • Cristiano Leite

    Deep cloning an instance of a type is the easiest when the type implements the IClonable interface correctly. You just have to call Clone() (i guess you figured that one out ). If the class you want to clone is not implementing IClonable you can either:

    Implement it yourself in an inheriting class of your own. Which means you will have to do that for every property class inside the class you want to clone recursively. This can mean that a lot of classes need to be inherited and their IClonable implementation to be written.

    Or....

    You write a method using reflection to read all the properties and set them in the new instance of the class. But be carefull remoting is slow, and you might need to make a recursive method which will make it even slower. (I can make you a code sample of this, but not now, i just woke up )

    Or....

    (Another thing that just popped in my mind, i never tried this myself). Serialize the object to disk or memory stream, then deserialize into another instance of the object. This might not work though since i don't think controls are serializable.

    Hope this sheds some light on the matter.


  • how can I deep clone an instance of any object?