84

I have the following Domain Object:

public class DomainClass
{
    public int Id { get; set; }

    public string A { get; set; }
    public string B { get; set; }
}

I have the following two objects that I want to map to:

public class Parent 
{
    public int Id { get; set; }
    public string A { get; set; }

    public Child Child { get; set; }
}

public class Child 
{
    public int Id { get; set; }
    public string B { get; set; }
}

I set up the following maps:

 Mapper.CreateMap<DomainClass, Parent>();
 Mapper.CreateMap<DomainClass, Child>();

If I map my object using the following call then the parent.Child property is null.

var domain = GetDomainObject();
var parent = Mapper.Map<DomainClass, Parent>(domain); // parent.Child is null

I know I can write the following:

var domain = GetDomainObject();
var parent = Mapper.Map<DomainClass, Parent>(domain);
parent.Child = Mapper.Map<DomainClass, Child>(domain);

Is there a way I can eliminate that second call and have AutoMapper do this for me?

Dismissile
  • 32,564
  • 38
  • 174
  • 263

4 Answers4

114

You just need to specify that in the mapping:

Mapper.CreateMap<DomainClass, Child>();
Mapper.CreateMap<DomainClass, Parent>()
      .ForMember(d => d.Id, opt => opt.MapFrom(s => s.Id))
      .ForMember(d => d.A, opt => opt.MapFrom(s => s.A))
      .ForMember(d => d.Child, 
                 opt => opt.MapFrom(s => Mapper.Map<DomainClass, Child>(s)));
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • 13
    Didn't think of calling Mapper.Map inside of MapFrom. Thanks – Dismissile Jan 20 '12 at 16:34
  • 56
    Just a heads up to other people who may see this now. This no longer works if you are using an IOC container to create an instance of your IMapper class. – PJH Jun 15 '16 at 15:30
  • 4
    Calling Mapper.Map inside your config also breaks ProjectTo with a LINQ to Entities error. – Shahin Dohan Jan 05 '17 at 06:46
  • @JustinNiessner, would this work here? http://stackoverflow.com/questions/41430679/automapper-update-entity-from-viewmodel-in-mvc – J86 Jan 05 '17 at 15:17
  • 4
    @PJH you can still map using `s=>s`, see my answer below – prostynick Jul 18 '17 at 14:30
  • I got this error when calling Mapper.Map inside "Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance." – dan Sep 26 '17 at 03:22
  • It doesn't work for me. I named all the items in both classes as the same. then it works for me. way choli chegadr too kholy. – AliNajafZadeh Feb 23 '22 at 11:37
  • I you use dependency injection you can't use `Mapper.Map` get the mapper in the context instead: `opt.MapFrom((s, d, context) => context.mapper.Map(s)));` – Pascal R. Apr 20 '23 at 10:44
54

Just map the child using self. Tested with AutoMapper 6.1.1.

        CreateMap<DomainClass, Child>();
        CreateMap<DomainClass, Parent>()
            .ForMember(d => d.Child, opt => opt.MapFrom(s => s));
Neutrino
  • 8,496
  • 4
  • 57
  • 83
prostynick
  • 6,129
  • 4
  • 37
  • 61
19

In Automapper 5.0 and above and if you are using Profile to create mapper:

public class OrderMapper : Profile
{
    public OrderMapper()
    {
        CreateMap<Order, OrderDto>(MemberList.None)
            .ForMember(dest => dest.OrderId,
                opts => opts.MapFrom(src => src.OrderId))
            .ForMember(dest => dest.OrderDate,
                opts => opts.MapFrom(src => src.OrderDate))
            .ForMember(dest => dest.OrderedBy,
                opts => opts.MapFrom(src => src.OrderedBy))
            .ForMember(dest => dest.ItemsDto,
                opt => opt.MapFrom(src => src.Items));
    }
}

where destination ItemsDto is a:

 public List<OrderItemDto> ItemsDto { get; set; }

and source Items is a:

  public List<OrderItem> Items { get; set; }

Then create a mapper profile for the child item/property:

public class OrderItemMapper : Profile
{
    public OrderItemMapper()
    {
        CreateMap<OrderItem, OrderItemDto>(MemberList.None)
            .ForMember(dest => dest.ItemId,
                opts => opts.MapFrom(src => src.ItemId))
            .ForMember(dest => dest.ItemPrice,
                opts => opts.MapFrom(src => src.ItemPrice))
            .ForMember(dest => dest.Name,
                opts => opts.MapFrom(src => src.Name))
            .ForMember(dest => dest.Quantity,
                opts => opts.MapFrom(src => src.Quantity))
            .ForMember(dest => dest.ItemTotal,
                opts => opts.MapFrom(src => src.ItemTotal));
    }

}
alltej
  • 6,787
  • 10
  • 46
  • 87
  • 1
    If you removed (or changed) the `MemberList.None` argument to `CreateMap()`, you wouldn't need those `.ForMember()` operations at all. That's what AutoMapper will map automatically. – Suncat2000 Oct 07 '21 at 18:29
2

Try This Way:

 _Mapper.Map<DomainClass, Child>();
         _Mapper.Map<DomainClass, Parent>()
            .ForMember(d => d.Child, opt => opt.MapFrom(s => s));
AliNajafZadeh
  • 1,216
  • 2
  • 13
  • 22