Automapper - How to map from source child object to destination
Asked Answered
W

1

7

I am trying to map from a child object of source to destination(as parent object).

Source Model:

public class SourceBaseResponse<T> where T : new()
{
    public string Type { get; set; }

    public string Id { get; set; }

    public T Attributes { get; set; }
}

For my example I am using T to be of type SourceAssignment

 public class SourceAssignment
{
    public string Id { get; set; }

    public string Email { get; set; }

    public string EmployeeId { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public DateTimeOffset CreatedAt { get; set; }

}

Destination Object

public class DestinationAssignment
{
    public string Id { get; set; }

    public string Email { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }
}

I want to map Source Model directly to Destination. So, I was trying to use

CreateMap<SourceAssignment, DestinationAssignment>();
CreateMap<SourceBaseResponse<SourceAssignment>, DestinationAssignment>()
            .ForMember(dest => dest, opt => opt.MapFrom(src => AutoMapperConfig.Mapper.Map<DestinationAssignment>(src.Attributes)));

This is not working as I am getting run time error in the above line that "Custom configuration for members is only supported for top-level individual members on a type."

So, as per this thread I tried the following

CreateMap<SourceBaseResponse<SourceAssignment>, DestinationAssignment>()
            .AfterMap((src, dst) => Mapper.Map(src.Attributes, dst));

Now, I am getting error where mapping should happen which says "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."

I am able to use ForMember for each property and map it from src.Attributes to dest(For eg: src.Attribute.Id to dest.Id). This works, but I do not really want to do this as my Source are complex classes involving nested childs(as this is a Web API response and I do not have control over this). So a lot of custom mapping is done here

CreateMap<SourceAssignment, DestinationAssignment>();

Any suggestions on how to proceed.

Whited answered 2/2, 2017 at 6:50 Comment(2)
The AfterMap expression uses the static Mapper, so make sure it is configured (i.e. static mapper has a map for SourceAssignment -> DestinationAssignment). Maybe you are currently configuring an instance instead of the static mapper?Kainite
@GeorgPatscheider It is a static mapper. I am able to use this for a automapping Source to Destination if not mapping from SourceBaseResponse.Whited
P
12

Resolution context is needed to be able to call Mapper.Map(), you can get resolution context by using ConstructUsing():

CreateMap<SourceChild, Destination>();
CreateMap<Source, Destination>()
    .ConstructUsing((src, ctx) => ctx.Mapper.Map<Destination>(src.SourceChild));
Potable answered 3/3, 2017 at 12:50 Comment(1)
This work great, except in tests. When creating a MapperConfiguration using this, config.AssertConfigurationIsValid() still fails, claiming that the properties of the child objects are unmapped.Erinerina

© 2022 - 2024 — McMap. All rights reserved.