1

I have the following abstract classes

public abstract class BaseClass
{
    public int NumberProperty { get; set; }
}

public abstract class BaseClass_DTO
{
    public int NumberProperty { get; set; }
    public string NumberPropertyAsString { get; set; }
}

and the following concrete class

public class ConcreteA : BaseClass
{
    public string StringProperty { get; set; }
}

public class ConcreteA_DTO : BaseClass_DTO
{
    public string StringProperty { get; set; }
}

And this is the Map

Mapper.Initialize( cfg => {
    cfg.CreateMap<BaseClass, BaseClass_DTO>()
        .ForMember( p => p.NumberPropertyAsString, opt => opt.MapFrom( x => x.NumberProperty.ToString() ) );
    cfg.CreateMap<ConcreteA, ConcreteA_DTO>()
        .IncludeBase<BaseClass, BaseClass_DTO>()
        .ReverseMap();
} );
Mapper.AssertConfigurationIsValid();

The code says that the configuration is not valid because of

Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
=============================================================================
ConcreteA_DTO -> ConcreteA (Source member list)
Temporary.Test.ConcreteA_DTO -> Temporary.Test.ConcreteA (Source member list)

Unmapped properties:
NumberPropertyAsString

The error happens because of the ReverseMap() call. How do I set the reverse map to ignore the member without duplicating the Map?

Lorenzo
  • 29,081
  • 49
  • 125
  • 222

1 Answers1

1

You will need to ignore the NumberPropertyAsString in the reverse map using

.ReverseMap()
   .ForSourceMember(p => p.NumberPropertyAsString, opt => opt.Ignore());

It appears that in your specific mapping config, you should make the configuration both in the base and the concrete as well.

1. In the base class map.

cfg.CreateMap<BaseClass, BaseClass_DTO>()
    .ForMember(p => p.NumberPropertyAsString, opt => opt.MapFrom(x => x.NumberProperty.ToString()))
    .ReverseMap()
          .ForSourceMember(p => p.NumberPropertyAsString, opt => opt.Ignore());

2. In the concrete class map.

cfg.CreateMap<ConcreteA, ConcreteA_DTO>()
    .IncludeBase<BaseClass, BaseClass_DTO>()
    .ReverseMap()
         .ForSourceMember(p => p.NumberPropertyAsString, opt => opt.Ignore());
Lorenzo
  • 29,081
  • 49
  • 125
  • 222
Alex
  • 13,024
  • 33
  • 62
  • Thanks for your answer. Yes. But unfortunately calling `ReverseMap()` will invert the types and for the first parameter of the call to `.ForMember()` I have a `BaseClass` type which do not have `NumberPropertyString` property. That's the way I asked "without duplicating the map". – Lorenzo Apr 04 '15 at 23:12
  • @Lorenzo Ah ok. It appears there is also a `ForSourceMember` that can be used to select a member of the source instead of target in the mapping. Note that since I don't have a project with Automapper installed right now, I can't check if this works. If it doesn't I'll do everyone a favor and delete this answer. – Alex Apr 04 '15 at 23:23
  • No problem. Let me try. This make more sense to me. Did'nt realized the existence of `ForSourceMember` – Lorenzo Apr 04 '15 at 23:25
  • Yes it works. The configuration should be made both in the abstract as well as the inherited class. I have edited your answer accordingly. Thank you! – Lorenzo Apr 04 '15 at 23:32
  • 1
    Cheers. It is somewhat surprising that the mapping config is required in both maps. – Alex Apr 04 '15 at 23:34
  • @Lorenzo I just wondered if for the concrete class map, the following would also have worked: `.ReverseMap().IncludeBase();`. – Alex Apr 05 '15 at 00:10