3

Recently I came up with an idea (that I really don't know whether it would exist or even work) of automatically updating a Class's properties using a modified instance of it. And, to make my idea a little bit more clear, I will explain it in the code below"

//The first (Main) instance of the Class
Employee carl = new Employee();
carl.Name = "Carl";
carl.Age = 20;
carl.Salary = 7000;

//Here is the same employee data collected from the database a year after:

Employee carl_one_year_later = new Employee();
carl_one_year_later.Age = 21;
carl_one_year_later.Salary = 10000;

//My idea is that I want to dynamically merge the new collected data to the current main instance of the employee, without missing out the unupdated data (i.e.: his name)
employee1 = employee2; //Using this seems to overwrite the Name Field with Null.

Some might say you can simply achieve this by doing this:

carl.Age = carl_one_year_later.Age;
carl.Salary = carl_one_year_later.Salary;

However, I want a dynamic way to just do this in 1 line of code and let C# handle the property set for me. Also, it may come in handy if we have a massive class that we don't want to set its properties every time they are updated one by one.

Community
  • 1
  • 1
Daniel Eugen
  • 2,712
  • 8
  • 33
  • 56
  • how about using reflection to iterate over properties and set those except which are null or default? – gp. Oct 16 '13 at 03:07
  • @gp.: Sorry i don't have experience with reflection, and if it really does what i am talking about, and in 1 line or (the less as possible). You may provide me with an detailed answer about how i could achieve it. – Daniel Eugen Oct 16 '13 at 03:09
  • Also, don't forget to take into account that as you say, i only want to get from the updated class the values that are not (null, or default) and set those value to the default main class... – Daniel Eugen Oct 16 '13 at 03:11
  • We used to have this in COBOL, and I sometimes wish we still did. It was called [MOVE CORRESPONDING](http://stackoverflow.com/questions/719135/whats-the-bright-side-of-cobol/719176#719176). – John Saunders Oct 16 '13 at 04:19

5 Answers5

2
using System;
using System.Reflection;

public class Test
{
    public class Employee
    {
        public String Name{get;set;}
        public int Age{get;set;}
        public int Salary{get;set;}
    }
    public static void Main()
    {
        Employee e1 = new Employee{Name="Old", Age=20, Salary=1000};
        Employee e2 = new Employee{Age=30, Salary=5000};

        Copy(e2, e1);

        Console.WriteLine(e1.Name+" "+ e1.Age+" "+e1.Salary );
    }

    public static void Copy<T>(T from, T to)
    {
        Type t = typeof (T);
        PropertyInfo[] props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (PropertyInfo p in props) {
            if (!p.CanRead || !p.CanWrite) continue;

            object val = p.GetGetMethod().Invoke(from, null);
            object defaultVal = p.PropertyType.IsValueType ? Activator.CreateInstance(p.PropertyType) : null;
            if (null != defaultVal && !val.Equals(defaultVal)) {
                p.GetSetMethod().Invoke(to, new[] {val});
            }
        }
    }
}
Daniel Eugen
  • 2,712
  • 8
  • 33
  • 56
gp.
  • 8,074
  • 3
  • 38
  • 39
1

You can make a CopyTo extension method, like so:

public static class ObjectExtensions
{
    public static void CopyTo<T>(this T fromObj, T toObj)
    {
        foreach(var p in typeof(T).GetProperties()) 
        {
            p.SetValue(toObj, p.GetValue(fromObj, null), null);
        }
    }
}

And call it like:

carl_one_year_later.CopyTo(carl);

Although, to be honest, there's a few more checks that should be made, and you'd be better off using something like AutoMapper instead.

rossipedia
  • 56,800
  • 10
  • 90
  • 93
0

Checkout ICloneable OR MemberwiseClone (unless you need to do a deep copy. Then check out a object mapper like Automapper, ValueInjecter or write your own custom object serialization hydrater)

http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx

The MemberwiseClone method creates a shallow copy by creating a new object, and then copying the nonstatic fields of the current object to the new object.

http://msdn.microsoft.com/en-us/library/system.icloneable.aspx

Alternatives to AutoMapper

Community
  • 1
  • 1
Chris McKelt
  • 1,378
  • 2
  • 17
  • 38
0
public static class ObjectExtensions
    {
        public static void CopyTo<T>(this T fromObj, T toObj)
        {
            foreach (var p in typeof(T).GetProperties())
            {
                if(p.GetValue(fromObj) == null)
                {
                    continue;
                }
                p.SetValue(toObj, p.GetValue(fromObj, null), null);
            }
        }
    }

Same as the above answer but just added "if" in "foreach" to skip the null values

Hinco
  • 1
-1

The idea itself seems odd to me..

I, myself, would just rather do :

//The first (Main) instance of the class
Employee carl = new Employee();
carl.Name = "Carl";
carl.Age = 20;
carl.Salary = 7000;

//Here we get Carl from the database
Employee carl = GetFromDatabase("Carl") //Illustration
carl.Age = 21;
carl.Salary = 10000;

Your code is like saying nowadays Carl and next year Carl is a completely different person, and coincidentally having all those same attributes.

Although if it really needs to be done, I do tend to prefer Automapper..

Samuel Adam
  • 1,327
  • 4
  • 26
  • 45