Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# merge two objects together at runtime

Tags:

I have a situation where I am loading a very unnormalized record set from Excel. I pull in each row and create the objects from it one at a time. each row could contain a company and / or a client.

My issue is that multiple rows could have the same objects, so I may have already created it. I do a comparison to see if it is already in the list. If so I need to merge the two objects to ensure I have not gained any new information from the second row.

so:

company   - client   - address   - phone ---------------------------------------- mycompany -          - myaddress -  mycompnay - myclient -           - myphone 

so the first row would create a company object with an address of "myaddress". The second row would create another company object (which by my rules is the same company as the name is the same), this also having a client reference and a phone number.

So I would know they are the same but need to ensure all the data is merged into one object.

At the moment I am creating a utility class that takes both objects, (one being the primary and the other to be merged, so one has priority if there is a clash), it goes through each variable and assigns the values if there are any. This is a bit boiler plate heavy and I was hoping there might be some utility I could utilize to do the manual work for me.

The example has been simplified as there are a fair few other variables, some basic types and others that are more complex items.

like image 391
Jon Avatar asked Mar 07 '10 13:03

Jon


2 Answers

Reflection would work. Something like:

public static void MergeWith<T>(this T primary, T secondary) {     foreach (var pi in typeof(T).GetProperties()) {        var priValue = pi.GetGetMethod().Invoke(primary, null);        var secValue = pi.GetGetMethod().Invoke(secondary, null);        if (priValue == null || (pi.PropertyType.IsValueType && priValue.Equals(Activator.CreateInstance(pi.PropertyType)))) {           pi.GetSetMethod().Invoke(primary, new object[]{secValue});        }     } } 
like image 106
Mark Brackett Avatar answered Sep 20 '22 21:09

Mark Brackett


I'd try to split this up: divide and conquer.

First, read all the objects in one huge list.

In a second step, select distinct lists using your primary key, for example, the company name. From the distinct list, use the item (the master) that has the largest number of fields set. Then, iterate over all the fields that are not yet in the master and merge their values in. LINQ will help you a lot in many of these steps without the need to code complicated algorithms manually.

This allows to customize the logic easily later, e.g. if you have a different set of 'primary keys' so to speak or if you want to do special comparisons of particular fields.

like image 34
mnemosyn Avatar answered Sep 21 '22 21:09

mnemosyn