How to clone an object in c #

3

I'm trying to duplicate a viewmodel, req is a viewmodel of the same type as copiaReq that arrives me by parameter

RequestMeetingRoom copiaReq = new RequestMeetingRoom();
copiaReq = req;
copiaReq.IdMeetingRoom = 3;

The problem is that when I change the id to copiaReq it also changes in req . How can you avoid that?

    
asked by Borja Calvo 10.08.2016 в 13:22
source

3 answers

1

One option is using the ICloneable

class claseOriginal  : ICloneable
{
    public String titulo;
    public String descripcion;
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

Implementing the interface and using Clone () the copy is made:

claseOriginal miClase = new claseOriginal();
//Copia de clase claseOriginal 
claseOriginal claseCopia = (claseOriginal)miClase.Clone();

Another option using Deep Cloning:

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

public static T DeepClone<T>(T obj)
{
 using (var ms = new MemoryStream())
 {
   var formatter = new BinaryFormatter();
   formatter.Serialize(ms, obj);
   ms.Position = 0;

   return (T) formatter.Deserialize(ms);
 }
}
    
answered by 10.08.2016 / 17:05
source
1

Normally you do not need to clone a whole graph of objects but in case you really need it you can use this library:

  

Disclaimer : I am the creator of the library

Minicloner

This library allows you to do a deep cloning of any .NET object including generics, dynamic, primitive types, references, circulars, etc.

The way of use is the following:

var cloner = new Minicloner.Cloner<RequestMeetingRoom>();
RequestMeetingRoom copiaReq = cloner.Clone(req);
copiaReq.IdMeetingRoom = 3;

Now if it is true that after modifying the IdMeetingRoom :

copiaReq.IdMeetingRoom != req.IdMeetingRoom

There is still no formal release of the project although I plan to release it soon. But being an open source project the source is free to be used.

This is the link to the relevant files:

answered by 11.08.2016 в 20:51
0

This happens because the classes are reference types .

There are several ways to solve it

Implement cloning

     public class RequestMeetingRoom
     {

        public RequestMeetingRoom Clone()
        {
            return (RequestMeetingRoom)this.MemberwiseClone();
        } 
     }

This will create a shallow copy or shallow copy I think that in your case is enough.

Although there is an interface called ICloneable there has been a lot of discussion must use or not. Read link . In any case, to use the MemberwiseClone() method, it is not necessary to implement it for what is left to your decision.

Use reflection

Using reflection you can copy all the values of the object and copy in depth the values that are by reference. This can be complicated and always depends on the type of object you have since the values can be quite complex.

     public class RequestMeetingRoom
     {

        public RequestMeetingRoom Clone()
        {
            var t = new RequestMeetingRoom();
            var type = t.GetType();

            foreach (var prop in type.GetProperties())
            {
                var p = type.GetProperty(prop.Name);
                p.SetValue(t, p.GetValue(this));
            }

            return t;
        } 
     }

This also creates a shallow copy (and only copies properties) but it's just to illustrate the point. Check out link

Serialization

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

     [Serializable]
     public class RequestMeetingRoom
     {

        public RequestMeetingRoom Clone()
        {
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();
            using (stream)
            {
                formatter.Serialize(stream, this);
                stream.Seek(0, SeekOrigin.Begin);
                return (RequestMeetingRoom)formatter.Deserialize(stream);
            }
        } 
     }

This has the disadvantage that you must use the referenced namespaces:

System.Runtime.Serialization
System.Runtime.Serialization.Formatters.Binary
System.IO

You must also mark your class as serializable and all instances of classes that contain your object must also be serializable so that it can work.

Use Automapper

    Mapper.CreateMap<RequestMeetingRoom, RequestMeetingRoom>();
    Mapper.Map<RequestMeetingRoom, RequestMeetingRoom>(copiaReq , req);  

This is usually the simplest since the library is robust and handles all the heavy lifting.

    
answered by 10.08.2016 в 15:42