Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Consider I download my data into this data structures:

public class AThingDTO
{
   int AID { get; set; }
   string AName { get; set;}
   Dictionary<int, BThingDTO> BThingsColl { get; set;} 
}

public class BThingDTO
{
   int BID { get; set; }
   string BName { get; set;}
   int AID { get; set; }
   List<CThingDTO> CThingsColl { get; set;}
}

public class CThingDTO
{
   int CID { get; set; }
   string CName { get; set;}
   int BID { get; set; }
   int AID { get; set; }
}

Consider I want to map it into this data structures:

public class AThing
{
   int AID { get; set; }
   string AName { get; set;}
   List<BThing> BThingsColl { get; set; } = new List<BThing>();
}

public class BThing
{
   int BID { get; set; }
   string BName { get; set;}
   List<CThing> CThingsColl { get; set;} = new List<CThing>();
}

public class CThing
{
   int CID { get; set; }
   string CName { get; set;}
}

I did like this:

public List<AThing> MapFromDTO(Dictionary<int, AThingDTO> dtoThingsHierarchy)
{
    var mappedThings = new List<AThing>();

    foreach (var aThingDto in dtoThingsHierarchy)
    {
        var aThing = new AThing();
        aThing.AID = aThingDto.AID;
        aThing.AName = aThingDto.AName;

        foreach (var bThingDto in BThingsColl.Values)
        {
            var bThing = new BThing();
            bThing.BID = bThingDto.BID;
            bThing.BName = bThingDto.BName;

            foreach (var cThingDto in CThingsColl)
            {
                var cThing = new CThing();
                cThing.CID = cThingDto.CID;
                cThing.CName = cThingDto.CName;

                bThing.CThingsColl.Add(cThing);
            }

            aThing.BThingsColl.Add(bThing);

        }

        mappedThings.Add(aThing);

    }

    return mappedThings;
}

Is there a more elegant way / more expressive way to express this mapping? Maybe with LINQ?

share|improve this question

closed as off-topic by Heslacher, BCdotWEB, rolfl, Malachi, mdfst13 Apr 26 at 13:29

This question appears to be off-topic. The users who voted to close gave this specific reason:

If this question can be reworded to fit the rules in the help center, please edit the question.

    
Questions must involve real code that you own or maintain. Pseudocode, hypothetical code, or stub code should be replaced by a concrete example. Questions seeking an explanation of someone else's code are also off-topic. – Heslacher Apr 26 at 10:24
2  
Wouldn't it be easier to just use AutoMapper? – BCdotWEB Apr 26 at 11:12
    
I agree with you! My question is also a little for curiosity – Francesco B. Apr 26 at 12:15
    
Have AThing contain a AThingDTO, et cetera. – radarbob Apr 26 at 12:55
up vote 2 down vote accepted

The first thing you can do is assign all the properties for a thing in one line using an object initializer. The following:

var cThing = new CThing();
cThing.CID = cThingDto.CID;
cThing.CName = cThingDto.CName;

would become:

var cThing = new CThing {CID = cThingDto.CID, CName = cThingDto.CName};

You can create a list before creating the parent thing so you can assign in the object initializer. I don't think your code works currently because you're not specifying the DTO in the foreach loops and not getting the values from the dictionary that's passed in. If the object initializer is too long, you can expand it to multiple lines or create and use a constructor for each class.

public List<AThing> MapFromDTO(Dictionary<int, AThingDTO> dtoThingsHierarchy)
{
    var mappedThings = new List<AThing>();

    foreach (var aThingDto in dtoThingsHierarchy.Values)
    {           
        var aThing = new AThing {AID = aThingDto.AID, AName = aThingDto.AName};
        foreach (var bThingDto in aThingDto.BThingsColl.Values)
        {
            var bThing = new BThing {BID = bThingDto.BID, BName = bThingDto.BName};
            foreach (var cThingDto in bThingDto.CThingsColl)
            {
                var cThing = new CThing {CID = cThingDto.CID, CName = cThingDto.CName};                 
                bThing.CThingsColl.Add(cThing);
            }               
            aThing.BThingsColl.Add(bThing);             
        }           
        mappedThings.Add(aThing);           
    }       
    return mappedThings;
}

Here's one way to rewrite your code using LINQ's method syntax:

public List<AThing> MapFromDTO(Dictionary<int, AThingDTO> dtoThingsHierarchy)
{       
    return dtoThingsHierarchy.Values
        .Select(a => new AThing {AID = a.AID, AName = a.AName, BThingsColl = a.BThingsColl.Values
            .Select(b => new BThing{ BID = b.BID, BName = b.BName, CThingsColl = b.CThingsColl
                .Select(c => new CThing {CID = c.CID, CName = c.CName}).ToList()}).ToList()}).ToList();
}

Here's LINQ's query syntax:

public List<AThing> MapFromDTO(Dictionary<int, AThingDTO> dtoThingsHierarchy)
{       
    return
       (from a in dtoThingsHierarchy.Values
        let bThings = 
           (from b in a.BThingsColl.Values
            let cThings = b.CThingsColl.Select(c => new CThing {CID = c.CID, CName = c.CName}).ToList()
            select new BThing{ BID = b.BID, BName = b.BName, CThingsColl = cThings }).ToList()
        select new AThing {AID = a.AID, AName = a.AName, BThingsColl = bThings}).ToList();
}

Both LINQ methods are quite a bit shorter, but the tradeoff in this case is they're kind of tough to read. Moving logic to the constructors could help.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.