SexyMF
SexyMF

Reputation: 11155

C# Merge 2 objects of the same with linq 2 object

public class SomePropertyClass{
    public string VarA{get;set;}
    public string VarB{get;set;}
}

SomePropertyClass v1 = new SomePropertyClass(){VarA = "item 1"};
SomePropertyClass v2 = new SomePropertyClass(){VarB = "item 2"};

Is it possible to create a third variable that will have:

v3: VarA = "item 1",VarB = "item 2"

I mean, I want to merge objects with linq to object.

Edit
for now i need from the same type. but it would be nice in the future to merge by property name.

I have an account model with a lot of properties that the user input in step 1.
I want to merge this half full model with step 2 half full model.

Edit 2

//step 1
        GlobalOnBoardingDataModel step1= (GlobalOnBoardingDataModel)HttpContext.Current.Session[SessionVariableNameStepOne];
//step 2           
        GlobalOnBoardingDataModel step2 = (GlobalOnBoardingDataModel)HttpContext.Current.Session[SessionVariableNameStepTwo];



     class GlobalOnBoardingDataModel {
        public string Email;//step 1
        public string Name;//step 1
        public string Phone;//step2
        public string Address;//step2
        }
    }

thanks

Upvotes: 0

Views: 18826

Answers (3)

toddmo
toddmo

Reputation: 22396

Here's the answer to the OP's question which is:

  • an exact answer
  • for two objects of the same type
    • (for two objects of different types the code would be almost identical)
  • a solution that is not hard coded
  • using linq
  • that respects non-nullity of source values
  • that doesn't need an external library
  • in one line of code.
public static T Merge<T>(T target, T source)
{
  typeof(T)
  .GetProperties()
  .Select((PropertyInfo x) => new KeyValuePair<PropertyInfo, object>(x, x.GetValue(source, null)))
  .Where((KeyValuePair<PropertyInfo, object> x) => x.Value != null).ToList()
  .ForEach((KeyValuePair<PropertyInfo, object> x) => x.Key.SetValue(target, x.Value, null));

  //return the modified copy of Target
  return target;
}

Upvotes: 9

Seb Boulet
Seb Boulet

Reputation: 981

Here's a way to accomplish this using reflection:

public class SomePropertyClass
{
    public string VarA { get; set; }
    public string VarB { get; set; }
}

static class Program
{
    static void Main(string[] args)
    {
        SomePropertyClass v1 = new SomePropertyClass() { VarA = "item 1" };
        SomePropertyClass v2 = new SomePropertyClass() { VarB = "item 2" };

        var yo = v1.Combine(v2);
    }

    static public IEnumerable<object> Combine<T, U>(this T one, U two)
    {
        var properties1 = one.GetType().GetProperties().Where(p => p.CanRead && p.GetValue(one, null) != null).Select(p => p.GetValue(one, null));
        var properties2 = two.GetType().GetProperties().Where(p => p.CanRead && p.GetValue(two, null) != null).Select(p => p.GetValue(two, null));

        return new List<object>(properties1.Concat(properties2));
    }
}

Upvotes: 3

Ian Mercer
Ian Mercer

Reputation: 39277

Do you mean something like this ... a Merge method that takes whichever value is not null from the matching properties?

public class SomePropertyClass{
    public string VarA{get;set;}
    public string VarB{get;set;}

    public SomePropertyClass Merge (SomePropertyClass other)
    {
       return new SomePropertyClass 
                    { VarA = this.VarA ?? other.VarA, 
                      VarB = this.VarB ?? other.VarB 
                    };
    }

If you wanted a solution that would work for any class you'd need to use reflection to find all the properties and then copy the missing ones. }

Upvotes: 3

Related Questions