22

I have 1 class that I need t map into multiple classes, for eg.

This is the source that I'm mapping from(view model):

public class UserBM
{
    public int UserId { get; set; }

    public string Address { get; set; }
    public string Address2 { get; set; }
    public string Address3 { get; set; }
    public string State { get; set; }

    public int CountryId { get; set; }
    public string Country { get; set; }
}

This is how the destination class is(domain model):

public abstract class User
{
    public int UserId { get; set; }

    public virtual Location Location { get; set; }
    public virtual int? LocationId { get; set; }
}

public class Location
{
    public int LocationId { get; set; }

    public string Address { get; set; }
    public string Address2 { get; set; }
    public string Address3 { get; set; }
    public string State { get; set; }

    public virtual int CountryId { get; set; }
    public virtual Country Country { get; set; }

}

This is how my automapper create map currently looks:

Mapper.CreateMap<UserBM, User>();
Shawn Mclean
  • 56,733
  • 95
  • 279
  • 406

3 Answers3

33

Define two mappings, both mapping from the same source to different destinations. In the User mapping, map the Location property manually using Mapper.Map<UserBM, Location>(...)

Mapper.CreateMap<UserBM, Location>();
Mapper.CreateMap<UserBM, User>()
    .ForMember(dest => dest.Location, opt => 
         opt.MapFrom(src => Mapper.Map<UserBM, Location>(src));
Andrew Whitaker
  • 124,656
  • 32
  • 289
  • 307
  • how can you do the opposite? – xrklvs Apr 14 '16 at 10:34
  • 11
    There's a similar thread on [SO](http://stackoverflow.com/questions/5984640/automapper-class-and-nested-class-map-to-one-class), where I like better the final bit of mapping: instead of `opt.MapFrom(src => Mapper.Map(src)`, it uses a simpler `opt => opt.MapFrom(src => src)` – superjos Dec 09 '16 at 12:03
  • Also @superjos using the simpler version also means it's compatible with using projection expressions which you can then pass down to entity framework, mongo, or any database provider capable of handling Expression> lambdas – Buvy Sep 09 '21 at 06:16
2

I have another solution. The main idea is that AutoMapper know how to flatten nested objects when you name properly properties in flattened object: adding nested object property name as a prefix. For your case Location is prefix:

public class UserBM
{
    public int UserId { get; set; }

    public int LocationId { get; set; }
    public string LocationAddress { get; set; }
    public string LocationState { get; set; }
    public string LocationCountry { get; set; }
    ...
}

So creating familiar mapping from nested to flattened and then using ReverseMap method allows AutomMapper to understand how to unflatten nested object.

CreateMap<UserBM, User>()
   .ReverseMap();

That's all!

Andrei
  • 749
  • 6
  • 7
1

I'm using Automapper 9 and the answers above didn't work for me. Then for resolve my problem that is like yours I use .afterMap, like that:

public class AutoMapperUser : Profile
{
        public AutoMapperUser ()
        {
            CreateMap<UserBM, User>()
                .AfterMap((src, dest, context) => dest.Location = context.Mapper.Map<UserBM, Location>(src));
        }
    }
}

I hope to help somebody.

Rodolfo Luna
  • 829
  • 9
  • 19