tyteen4a03
tyteen4a03

Reputation: 1932

AutoMapper map source property into inner destination object

I have one source class:

class Source {
    public string Name;
    public string Field1;
    public string Field2;
}

and two destination classes:

class Destination {
    public string Name;
    public FieldsDto Fields;
}

class FieldsDto {
    public string Field1;
    public string FieldTwo;
}

How can I map Source.Field1 to Destination.Fields.Field1 and Source.Field2 to Destination.Fields.FieldTwo?

This code does not work; it would throw an error saying that Custom configuration for members is only supported for top-level individ ual members on a type1:

Mapper.Initialize(cfg => {
    cfg.CreateMap<Source, Destination>()
        .ForMember(dest => dest.Fields.Field1, opt => opt.Mapfrom(src => src.Field1)
        .ForMember(dest => dest.Fields.FieldTwo, opt => opt.Mapfrom(src => src.Field2);
});

Upvotes: 3

Views: 3503

Answers (1)

poke
poke

Reputation: 387557

As mentioned in the comments, in order to map nested properties, you will need to use ForPath instead of ForMember. So a full configuration may look like this:

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<Source, Destination>()
        .ForMember(dest => dest.Name, opt => opt.MapFrom(s => s.Name))
        .ForPath(dest => dest.Fields.Field1, opt => opt.MapFrom(src => src.Field1))
        .ForPath(dest => dest.Fields.FieldTwo, opt => opt.MapFrom(src => src.Field2));
});

If you want to do this dynamically, using member names as string (which appears like something you want to do, as I learned in chat), then you will not be able to use ForPath easily since that absolutely requires a lambda expression that contains only a member expression.

What you could do is create a lambda expression dynamically for the nested member access. I’m sure you will find enough examples on how to create such lambda expressions on here if you search for it.

The alternative would be to split up the mapping into the separate types. So instead of mapping directly to nested properties of the Destination, you are mapping the nested object separately. Like this:

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<Source, FieldsDto>()
        .ForMember("Field1", opt => opt.MapFrom("Field1"))
        .ForMember("FieldTwo", opt => opt.MapFrom("Field2"));
    cfg.CreateMap<Source, Destination>()
        .ForMember(dest => dest.Name, opt => opt.MapFrom(s => s.Name))
        .ForMember(dest => dest.Fields, opt => opt.MapFrom(s => Mapper.Map<FieldsDto>(s)));
});

Upvotes: 4

Related Questions