Buduls
Buduls

Reputation: 115

How to use automapper to map Parent of source type into a collection of destination type?

I have these classes:

public class Source 
{
    public string ID { get; set; }
    public int Age Name { get; set; }
    public virtual ICollection<SourceChild> SourceChildren { get; set; }
}

public class SourceChild 
{
    public string Name { get; set; }
    public string Language { get; set; }
    public string SourceId { get; set; }
    public virtual Source Source { get; set; }
}

public class Destination
{
    public int Age { get; set; }
    public string Name { get; set; }
    public string Language { get; set; }
    public string Id { get; set; }
}

I was mapping these classes using these mappings:

        Mapper.CreateMap<SourceChild, Destination>()
            .ForMember(item => item.ID, property => property.MapFrom(item => item.SourceId))
            .ForMember(item => item.Age, property => property.MapFrom(item => item.Source.Age));

Automapper maps the other two properties automatically. So everything works fine if I try to map SourceChild into Destination type. However now I have another class using source and destination types:

public class SourceUser 
{
    public string ID { get; set; }
    public virtual Source Source { get; set; }
}

public class DestinationUser
{
    public string Id { get; set; }
    public List<Destination> Destinations { get; set; } 
}

To illustrate the situation better here is short description on the classes: I have Source object and SourceChild children objects. SourceChild objects contain information in different languages. When I map Source into Destination I want to input the Source object and receive output of a collection of destination objects. For each SourceChild object, Source object had, there should be one Destination object.SourceUser simply refers to Source with a 1-many relation. DestinationUser had a many - many retion with Destination class. In other words each DestinationUser has a list of all Destinations in all languages. So having all this in mind let's get back to the code.

I have had some luck in writing the code I need. I have come up with this:

 Mapper.CreateMap<SourceUser, DestinationUser>()
                .AfterMap((source, destination) => Mapper.Map<Source, List<Destination>>(source.Source));

    Mapper.CreateMap<Source, List<Destination>>()
                    .AfterMap((source, destination) => Mapper.Map<List<SourceChild>, List<Destination>>(source.SourceChildren.ToList(), destination));

This works ALMOST well enough, there is one IF though. I am using queryable extensions to process the mapping. When I retrieve a collection of DestinationUsers, none of them have the property Destinations mapped. It appears as null. However, if I do the mapping manually like this:

SourceUser SourceUser = Db.GetSourceUser();
DestinationUser DestUser = Db.GetDestinationUser();
DestUser.Destinations = Mapper.Map<List<Destination>>(SourceUser.Source);

everythign works fine. A list fo DestinationUsers is mapped from the instance of Source.

is it possible to avoid manually calling the latter Mapper.Map() call? Also bear in mind, that the List Destinations may be changed into any other collection. I just want to have a Destination object for each SourceChild object Source had.

Upvotes: 1

Views: 2857

Answers (1)

Buduls
Buduls

Reputation: 115

Turns out I was only one little step away from the solution I was after. All I needed was extending my mapping of SourceUser and DestinationUser classes to look like this:

Mapper.CreateMap<SourceUser, DestinationUser>()
                .AfterMap((source, destination) => Mapper.Map<Source, List<Destination>>(source.Source, destination.Destinations));

Hope this helps someone, experiencing similar problems to the one I was facing :)

Upvotes: 4

Related Questions