Search code examples
c#linqxmlserializer

Join two lists of objects: All properties from one list, only certain properties from the other one


I have two classes:

class Class1
{
    public int ProductId  { get; set; }
    public string ProductName  { get; set; }
    public int Amount  { get; set; }
    public string Category { get; set; }
}

class Class2
{
    public id ProductId  { get; set; }
    public DateTime UpdateTime { get; set; }
    public int ItemState  { get; set; }
    public decimal Price { get; set; }
    public string ImageUrl { get; set; }
}

I create two lists for each of this class:

public List<Class1> listClass1 { get; set; } = new List<Class1>();
public List<Class2> listClass2 { get; set; } = new List<Class2>();

Now I want to create a new list by joining both lists on the ProductID containing all properties from Class1 and just UpdateTime and ItemState from Class2. What is the best way to do this?

(The ultimate goal is to let the user save the current session to let him continue with his work later, for this I need the complete listClass1 and the mentioned properties of listClass2. The idea is to use an XmlSerializer on the merged list and save it into an XML file. To open the file, I want to deserialize it. If you have a better approach to let the user save his session, I'm all ears.)


Solution

  • I would suggest to make a third class which represents the joined parameter set.

    public class Class1_2
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public int Amount { get; set; }
        public string Category { get; set; }
    
        public DateTime UpdateTime { get; set; }
        public int ItemState { get; set; }
    }
    

    How to join 2 Lists is described in LINQ Join 2 Lists. So you would end up with something like this:

    List<Class1_2> joinedList = (from item1 in listClass1
                                 join item2 in listClass2
                                 on item1.ProductId equals item2.ProductId
                                 select new Class1_2
                                 {
                                     ProductId = item1.ProductId,
                                     Amount = item1.Amount,
                                     ProductName = item1.ProductName,
                                     Category = item1.Category,
                                     ItemState = item2.ItemState,
                                     UpdateTime = item2.UpdateTime
                                 }).ToList();
    

    Explanation: You join the items on the particular property. If it is equal in both lists you take the item and construct a new one with the selected properties. The join would also work without Class1_2 but then you get a result of dynamic type. The advantage of the new Class_1_2 is that you can use it for serialization with a defined structure.

    EDIT

    you could also use a second constructor in Class1_2

    public Class1_2(Class1 c1, Class2 c2)
    {
        ProductId = c1.ProductId;
        Amount = c1.Amount;
        ProductName = c1.ProductName;
        Category = c1.Category;
        ItemState = c2.ItemState;
        UpdateTime = c2.UpdateTime;
    }
    

    that would simplify a little the select statement to:

    select new Class1_2(item1, item2)).ToList();