kavun kavun - 1 month ago 14
C# Question

What's the equivalent of Javascript's Object.assign() in C#

If I have a C# class

public class Foo
{
public int? a { get; set; }
public int? b { get; set; }
}


And two instances of that class

var foo1 = new Foo() { a = 1 };
var foo2 = new Foo() { b = 1 };


How could I copy the values from both objects to create a new instance of
Foo
that contained the values from both
foo1
and
foo2
?

In Javascript this would be as simple as

var foo3 = Object.assign({}, foo1, foo2);

Answer

you could create a method which merges objects via reflection. But beware, this is slow an can generally not used in C#.

Care must be taken to skip "empty" properties. In your case these are value types. In my example implementation, every property is skipped, if its the default value of that type (for int this is 0):

public T CreateFromObjects<T>(params T[] sources)
    where T : new()
{
    var ret = new T();
    MergeObjects(ret, sources);

    return ret;
}

public void MergeObjects<T>(T target, params T[] sources)
{
    Func<PropertyInfo, T, bool> predicate = (p, s) =>
    {
        if (p.GetValue(s).Equals(GetDefault(p.PropertyType)))
        {
            return false;
        }

        return true;
    };

    MergeObjects(target, predicate, sources);
}

public void MergeObjects<T>(T target, Func<PropertyInfo, T, bool> predicate, params T[] sources)
{
    foreach (var propertyInfo in typeof(T).GetProperties().Where(prop => prop.CanRead && prop.CanWrite))
    {
        foreach (var source in sources)
        {
            if (predicate(propertyInfo, source))
            {
                propertyInfo.SetValue(target, propertyInfo.GetValue(source));
            }
        }
    }
}

private static object GetDefault(Type type)
{
    if (type.IsValueType)
    {
        return Activator.CreateInstance(type);
    }
    return null;
}

usage:

var foo3 = CreateFromObjects(foo1, foo2);