Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper - How to map from source child object to destination

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.

like image 741
Sumesh Kuttan Avatar asked Feb 02 '17 06:02

Sumesh Kuttan


People also ask

How do I map a source and destination object in automapper?

Map has an overload that takes a source and destination object: d = AutoMapper.Mapper.Map<sourceone, destination> (sourceone); /* Pass the created destination to the second map call: */ AutoMapper.Mapper.Map<sourcetwo, destination> (sourcetwo, d);

How to quickly map a child/nested object to the flattened object?

After some discussion with OP, it turns out his main need is to quickly map a child/nested object inside the source object to the flattened destination object. He does not want to write a mapping for every property of the destination. Here is a way to achieve this: Define a mapping Product -> ProductViewModel used to flatten the members of Product

Why is mapper map() used instead of formembers()?

1) There are multiple members in the child and creating multiple .ForMembers () seems messy. 2) Mapper.Map () is used instead of directly accessing the object because this is done a parent generic provider class that uses mapping configurations. should accomplish what you're trying to do here.

How to Access Runtime mapper in Salesforce?

You can access the runtime mapper on the ResolutionContext. The error message is hard to understand, but it means you have to state the destination properties explicitly: You also have to define a mapping from Category to CategoryViewModel for


Video Answer


1 Answers

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));
like image 143
akl22 Avatar answered Oct 26 '22 03:10

akl22