IncludeBase and ForAllOtherMembers does not cooperate. When using ForAllOtherMembers the IncludeBase mappings are ignored.
// Source types
internal abstract class Base
{
public int Id { get; set; }
public DateTimeOffset Created { get; set; }
public DateTimeOffset Modified { get; set; }
}
internal class Person : Base
{
public string Name { get; set; }
public string IgnoredProperty { get; set; }
}
// Destination types
public abstract class BaseDTO
{
public int Id { get; set; }
public DateTimeOffset Created { get; set; }
public DateTimeOffset Modified { get; set; }
}
public class PersonDTO : BaseDTO
{
public string Name { get; set; }
public string IgnoredProperty { get; set; }
}
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Base, BaseDTO>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
.ForMember(dest => dest.Created, opt => opt.MapFrom(src => src.Created))
.ForMember(dest => dest.Modified, opt => opt.MapFrom(src => src.Modified));
cfg.CreateMap<Person, PersonDTO>()
// Include base mappings
.IncludeBase<Base, BaseDTO>()
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
// Ignore all other properties
.ForAllOtherMembers(opt => opt.Ignore()); // Removing this and it will work
});
The base mapping should be added with the IncludeBase even if ForAllOtherMembers is configured.
The mappings provided with the IncludeBase should be mapped even when ForAllOtherMembers is configured.
var p = new Person
{
Id = 1,
Created = DateTimeOffset.Now,
Modified = DateTimeOffset.Now,
Name = "A Test Name",
IgnoredProperty = "This is the ignored property."
};
var result = mapper.Map<PersonDTO>(p);
// This is mapped
Assert.Equal(p.Name, result.Name);
// Success because of ForAllOtherMembers option
Assert.Null(result.IgnoredProperty);
// Everything below here fails, while it shouldn't since IncludeBase is used
Assert.Equal(p.Created, result.Created);
Assert.Equal(p.Modified, result.Modified);
Assert.Equal(p.Id, result.Id);
Just use MemberList.None for that map. ForAllOtherMembers is tricky :)
@jbogard Here's another feature waiting for its earthly demise. Or smth.
Sigh. Probably so, I don't even know how it works or what it does 馃槅
It ignores everything not explicitly configured. It works by considering things at config time, which of course won't work for included maps. But stepping back, what does this do besides validation? I guess it ignores members that would otherwise match. Kind of anti AutoMapper. I'm not sure we really want that.
Ohhhh yes this is "ExplicitMapper", yeah what's the point of this mapping? Only map things I explicitly configure, and ignore the rest?
I guess :) Otherwise MemberList.None would do.
https://github.com/AutoMapper/AutoMapper/blob/565c9634e2a0b487c9b25bca20f67a43e0ee06a3/src/UnitTests/ForAllOtherMembers.cs#L39
Yeah but it's a little bit different than validation, this will ignore auto-mapped members too.
I think it should go, tbqh
Another option is a simple extension method:
public static IMappingExpression<TSource, TDestination> Ignore<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> mapping,
params Expression<Func<TDestination, object>>[] members)
{
foreach (var member in members)
{
mapping.ForMember(member, o => o.Ignore());
}
return mapping;
}
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.