5

There is a question, that describes what i want to get very precisely, but they are using inline mapping.

Source/destination types

public class SrcInner
{
    public int A {get;set;} // imagine here 100500 properties
}

public class SrcOuter
{
    public int B {get;set;}
    public SrcInner C {get;set}
}

public class Dest
{
    public int A {get;set;} // so here imagine 100500 same properties, as in SrcInner
    public int B {get;set;}
}

Mapping configuration

public static void AddMapper(this IServiceCollection services)
{
    var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<SrcInner, Dest>();
        cfg.CreateMap<SrcOuter, Dest>();
    });

    var mapper = config.CreateMapper();

    services.AddSingleton(mapper);
}

Expected behavior

Both A and B properties are filled after mapping.

Actual behavior

Only B property is filled after mapping.

Steps to reproduce

public class Foo
{
    IMapper Mapper{get;set;}
    public Foo(IMapper mapper) // comes through dependency injection
    {
        Mapper = mapper;
    }

    public Bar()
    {
        var test = new SrcOuter()
        {
            B = 10;
            C = new SrcInner()
            {
                A = 10;
            }
        }
        var testDest = new Dest();
        mapper.Map(test, Dest);
    }
}

Is there a proper way to set configuration that way, so such mapping will work?


UPDATE

Is there a way to map Dest to SrcOuter with filling SrcInner?

2 Answers 2

7

The documentation describes how this can be achieved using IncludeMembers here

In your case, the config would be:

cfg.CreateMap<SrcOuter, Dest>().IncludeMembers(s => s.C);
cfg.CreateMap<SrcInner, Dest>(MemberList.None);

If you want this to work both ways, the most idiomatic way to do this is to prefix your destination members with the nested source object name, so that flattening and unflattening works automatically.

E.g. if you have the following objects:

public class SrcInner
{
    public int A { get; set; }
}

public class SrcOuter
{
    public int B { get; set; }
    public SrcInner Inner { get; set; }
}

public class Dest
{
    public int InnerA { get; set; }
    public int B { get; set; }
}

You don't need any more configuration than:

cfg.CreateMap<SrcOuter, Dest>().ReverseMap();
Sign up to request clarification or add additional context in comments.

5 Comments

Is there a way to to do the same thing vice versa, i.e. to map Dest to SrcOuter with filling SrcInner?
According to the documentation, a call to .ReverseMap() should give you that
CreateMap<A, B>.ReverseMap() is just a sugar for CreateMap<B, A>, isn't it?
Is it possible you could add some of the important information from the link in your answer? Links can go bad over time and may include vital parts for future visitors to use to help solve a similar problem.
For some project architecture reasons a can't use .ReverseMap() and rename properties. So i can use just CreateMap<Dest, SrcOuter>.ForMember(srcOuter => srcOuter.C, member => member.MapFrom(dest => dest))
3

I think you need to look at this: https://docs.automapper.org/en/stable/Projection.html

And then you need to

 .ForMember(dest => dest.A, opt => opt.MapFrom(src => src.C.A))

1 Comment

ok, but imagine that in SrcInner class there are much more properties, than one. So i need to write ForMember for each such property, and it's definitely not okay

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.