5
 var _Contact = new ContactLstModel { 
             ContactName="xxxxxx",
              EmailAddr="yyyyyy",
               ContactNo="ddddddd",
               SelectedContactType="dddd"
            };

 var _ContactOption= new ContactLstModel{
                 ContactType= new List<SelectListItem>(){
                 new SelectListItem{
                  Text="sss",Value="ddd"
                 }
                 }
            };

as you can see both are of the same model ContactLstModel. Now how do I combine both into one?

Like in jQuery, we have $.extend(dest,source);

Is there an equivalent in C#?

Dave
  • 434
  • 5
  • 22
Irshu
  • 8,248
  • 8
  • 53
  • 65

3 Answers3

6

There is not a built-in equivalent of $.extend in C# and .NET 4.5.

However you can find many examples of people trying to achieve that kind of behavior using reflection in .NET. There are others who use serialization (JSON.NET etc.) to achieve similar behaviors . Another approach would be to use IOC containers like Automapper.

Here is an example how to merge your first object into the second object using Automapper IOC:

var expr = Mapper.CreateMap<ContactLstModel, ContactLstModel>().ForMember("ContactType", (conf) => { conf.Ignore(); });
var merged = Mapper.Map<ContactLstModel, ContactLstModel>(_Contact, _ContactOption);

With Automapper you can control how to map each single property from source to destination.

If you don't want external library dependencies, and want full control you can use a pure Reflection approach.

For example you could use something similar as the CopyValues method from this link and merge the second object properties with the first one using reflection.

CopyValues<ContactLstModel>(_Contact, _ContactOption);

So this line of code will copy the ContactType property values from the second object into the first one.

CopyValues uses reflection to loop through the properties of the objects:

public static void CopyValues<T>(T target, T source)
{
    Type t = typeof(T);

    var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);

    foreach (var prop in properties)
    {
        var value = prop.GetValue(source, null);
        if (value != null)
            prop.SetValue(target, value, null);
    }
}

Of course this does not support everything jquery extend does (merging, shallow and deep cloning into a new object etc.), but it can satisfy your current needs. You can extend on these principles and build a more comprehensive solution.

However have in mind that C# is not a language like Javascript, and the cost of doing reflection is much higher in C#, while in Javascript the properties of a prototype can be listed with a cheap for-in iteration, or with a call to Object.keys().

Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
Faris Zacina
  • 14,056
  • 7
  • 62
  • 75
  • Reflection is a bit slower than methods dedicated to specific objects (like in Tomas Lycken answer) and allow less control, but it's the most generic way to achieve this. – AFract Oct 02 '14 at 08:26
  • Yeah. JQuery extend merges the properties automatically without specifying the names, so a reflection based approach is probably the closest he can get to that kind of functionality. – Faris Zacina Oct 02 '14 at 08:33
3

You could do it with an extension method:

public static class ContactModelExtensions {
    public static ContactModel Extend(this ContactModel first, ContactModel replacement) {
        if (!replacement.ContactsName.IsNullOrEmpty()) // or whatever criteria you want
        {
            first.ContactsName = replacement.ContactsName;
        }
        // similar assignment for all other properties

        return first; // since we return the first one, properties not set in override
                      // will be untouched
    }
}

Now, you can just

var extendedContact = _Contact.Extend(_ContactOptions);

to get it done.

AFract
  • 8,868
  • 6
  • 48
  • 70
Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402
  • Nice proposition, and faster than reflection, but this specific example will certainly not compile since "override" is a reserved keyword. I've suggested an edit for it. – AFract Oct 02 '14 at 08:27
  • @Richard: Thanks. That's what I get for typing code off my head without testing it, I guess :P – Tomas Aschan Oct 02 '14 at 08:32
2

You can use some frameworks for do it. For example with ValueInjecter:

    public class NoNullsInjection : ConventionInjection
    {
        protected override bool Match(ConventionInfo c)
        {
            return c.SourceProp.Name == c.TargetProp.Name
                    && c.SourceProp.Value != null;
        }
    }

    class A
    {
        public string a { get; set; }
        public string b { get; set; }
    }

    static void Main(string[] args)
    {
        A a1 = new A() { a = "123" };
        A a2 = new A() { b = "456" };
        A c = new A();

        c.InjectFrom(new NoNullsInjection(),a1,a2); 
        // "c" now have a="123", b="456"     

    }
IVAAAN123
  • 557
  • 2
  • 9