Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copying All Class Fields and Properties To Another Class

Tags:

c#

I have a class which normally contains Fields, Properties. What i want to achieve is instead of this:

class Example
{
    public string Field = "EN";
    public string Name { get; set; }
    public int? Age { get; set; }
    public List<string> A_State_of_String { get; set; }
}

public static void Test()
{
    var c1 = new Example
    {
        Name = "Philip",
        Age = null,
        A_State_of_String = new List<string>
        {
            "Some Strings"
        }
    };
    var c2 = new Example();

    //Instead of doing that
    c2.Name = string.IsNullOrEmpty(c1.Name) ? "" : c1.Name;
    c2.Age = c1.Age ?? 0;
    c2.A_State_of_String = c1.A_State_of_String ?? new List<string>();

    //Just do that
    c1.CopyEmAll(c2);
}

What i came up with but doesn't work as expected.

public static void CopyEmAll(this object src, object dest)
{
    if (src == null) {
        throw new ArgumentNullException("src");
    }

    foreach (PropertyDescriptor item in TypeDescriptor.GetProperties(src)) {
        var val = item.GetValue(src);
        if (val == null) {
            continue;
        }
        item.SetValue(dest, val);
    }
}

Problems:

  • Although i checked for null, it seems to bypass it.
  • Doesn't seem to copy Fields.

Notes:

  • I don't want to use AutoMapper for some technical issues.
  • I want the method to copy values and not creating new object. [just mimic the behavior i stated in the example]
  • I want the function to be recursive [if the class contains another classes it copies its values too going to the most inner one]
  • Don't want to copy null or empty values unless i allow it to.
  • Copies all Fields, Properties, or even Events.
like image 981
Roman Ratskey Avatar asked Mar 21 '23 14:03

Roman Ratskey


1 Answers

Based on Leo's answer, but using Generics and copying also the fields:

public void CopyAll<T>(T source, T target)
{
    var type = typeof(T);
    foreach (var sourceProperty in type.GetProperties())
    {
        var targetProperty = type.GetProperty(sourceProperty.Name);
        targetProperty.SetValue(target, sourceProperty.GetValue(source, null), null);
    }
    foreach (var sourceField in type.GetFields())
    {
        var targetField = type.GetField(sourceField.Name);
        targetField.SetValue(target, sourceField.GetValue(source));
    }       
}

And then just:

CopyAll(f1, f2);
like image 79
thepirat000 Avatar answered Mar 31 '23 19:03

thepirat000