Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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);
like image 434
kavun Avatar asked Nov 03 '16 13:11

kavun


People also ask

What can I use instead of object assign?

assign() pattern in Node 8.

What is object assign ()?

Object.assign() The Object.assign() method copies all enumerable own properties from one or more source objects to a target object. It returns the modified target object.

Is object assign and spread operator same?

Spread in object literals Note that Object.assign() can be used to mutate an object, whereas spread syntax can't. In addition, Object.assign() triggers setters on the target object, whereas spread syntax does not.

How do you assign an array of objects?

By using a separate member method : By using a separate member method also we can initialize objects. A member function of the respective class is created and that is used to assign the initial values to the objects. The below program shows how the array of objects is initialized using a separate member method.


1 Answers

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);
like image 50
Nico Avatar answered Sep 30 '22 14:09

Nico