Similar types but with different objects. What is the best way to use it?

6

I had to create a new object but totally equal to that existing in the C # system. Since the objects are the same I tried to do:

ObjetoOriginal.Propriedades = ObjetoClone.Propriedades;

Unfortunately it does not work, does it?

I tried then:

ObjetoOriginal.Propriedades = (ObjetoOriginal)ObjetoClone.Propriedades;

And nothing.

So I had to do something like this:

ObjetoOriginal.Propriedades.A = ObjetoClone.Propriedades.A;

ObjetoOriginal.Propriedades.B = ObjetoClone.Propriedades.B;

What would be the best way to get all of the properties at once?

    
asked by anonymous 13.01.2017 / 00:17

3 answers

5

First point: You should think 10 times before cloning an object. It is often problematic to do this and almost always is not necessary.

If the object was intended to be cloned, it will implement the IClonable . I've already replied about this . And it is recommended to do this only where it is necessary and very conscientious. It's easy to do wrong.

It seems to me that you want to clone any object. If the object was not thought to be cloned it is almost certain that it is making a mistake, but can use reflection to do this without having to be copying each member manually. Ideally create a method to do this generically:

static class ObjectUtil<T> {
    public static T Clone(T obj) {
        Type type = obj.GetType();
        var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
        var cloned = Activator.CreateInstance(type);
        for (int i = 0; i < fields.Length; i++) {
            fields[i].SetValue(cloned, fields[i].GetValue(obj));
        }
        return (T)cloned;
    }   
}

See running on .NET Fiddle . And No Coding Ground . Also I put it in GitHub for future reference .

    
13.01.2017 / 01:03
2

Implement the ICloneable in your class that will allow you to clone a copy of the class with the same values, but being different objects. Within the method created by the implementation ICloneable call MemberwiseClone () that returns a copy in one new object.

Code:

public class Propriedades: ICloneable
{
    public Propriedades()
    {

    }
    public int Id { get; set; } = 1;
    public string Name { get; set; } = "Name 1";

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

Use:

Propriedades p = new Propriedades();
Propriedades c = (Propriedades)p.Clone(); //Clone "ICloneable"

Another way is to use reflection ( reflection ):

Propriedades propr1 = new Propriedades();
propr1.Id = 2;
propr1.Name = "Nome 2";
Type propType1 = propr1.GetType();

Propriedades propr2 = new Propriedades();
Type propType2 = propr1.GetType();

foreach(PropertyInfo info in propType1.GetProperties())
{
    propType2.GetProperty(info.Name)
        .SetValue(propr2, info.GetValue(propr1));
}

The above code can be simplified with

13.01.2017 / 00:41
2

I've added an alternative here, which might be useful if the class has a circular reference and you have mastery over it.

You can decorate it with the [DataContract] and [DataMember] and serialize its binary using the DataContractSerializer

follow the example.:

var serialize = new DataContractSerializer(typeof(MyClass));
var myClone = default(MyClass);
using (var stream = new MemoryStream())
{
    serialize.WriteObject(stream, myObject);
    stream.Position = 0;
    stream.Flush();
    myClone = (MyClass)serialize.ReadObject(stream);
}

For serialization with cyclic references, it is necessary to use the property IsReference of DataContrac with value equal to true ;

Here is a complete example.:

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;

namespace ConsoleApplication2
{
    [DataContract(IsReference = true)]
    public class Pessoa
    {
        [DataMember]
        public string Nome { get; set; }

        [DataMember]
        public Pessoa Companheiro { get; set; }

        [DataMember]
        public Pessoa Pai { get; set; }

        [DataMember]
        public Pessoa Mae { get; set; }

        [DataMember]
        public List<Pessoa> Filhos { get; set; }

        [DataMember]
        public List<Pessoa> Irmaos { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var pessoa1 = new Pessoa() { Nome = "Pai" };
            var pessoa2 = new Pessoa() { Nome = "Mãe" };
            var pessoa3 = new Pessoa() { Nome = "Filho 1" };
            var pessoa4 = new Pessoa() { Nome = "Filho 2" };
            var pessoa5 = new Pessoa() { Nome = "Filho 3" };

            pessoa1.Companheiro = pessoa2;
            pessoa2.Companheiro = pessoa1;
            pessoa1.Filhos = pessoa2.Filhos = new List<Pessoa> { pessoa3, pessoa4, pessoa5 };

            pessoa3.Pai = pessoa4.Pai = pessoa5.Pai = pessoa1;
            pessoa3.Mae = pessoa4.Mae = pessoa5.Mae = pessoa2;
            pessoa3.Irmaos = new List<Pessoa> { pessoa4, pessoa5 };
            pessoa4.Irmaos = new List<Pessoa> { pessoa3, pessoa5 };
            pessoa5.Irmaos = new List<Pessoa> { pessoa3, pessoa4 };

            var serialize = new DataContractSerializer(typeof(Pessoa));
            var clone = default(Pessoa);
            using (var stream = new MemoryStream())
            {
                serialize.WriteObject(stream, pessoa1);
                stream.Position = 0;
                stream.Flush();
                clone = (Pessoa)serialize.ReadObject(stream);
            }

            clone.Companheiro.Filhos[1].Nome = "Clone do Filho 2";
            Console.WriteLine($"{clone.Companheiro.Filhos[1].Nome}, {pessoa1.Companheiro.Filhos[1].Nome}, {pessoa4.Nome}");
        }
    }
}
    
13.01.2017 / 13:36