I've been looking everywhere: stackoverflow, automapper documentation, internets and just couldn't find any info on this one, even tho this seems to be a very common problem.
My mapping:
CreateMap<StatusLevelDTO, StatusLevel>()
.ForAllMembers(opt => opt.Condition(src => src != null));
This doesn't work because src represents source object (StatusLevelDTO), not a source property (I think).
To be more specific, If I map ObjectA to ObjectB, ObjectA.SomeValue is null and ObjectB.SomeValue is 2, I want the destination object to keep its value (2).
I've seen this question: Automapper skip null values with custom resolver and tried the first two answers but they both seem to be outdated for version 6.
Is there any way to make this happen in Automapper 6? I am using 6.0.2 to be exact.
Method Condition
now has five overloads, one of which accepts predicate of type
Func<TSource, TDestination, TMember, bool>
this TMember parameter is the source member. So you can check source member for null:
CreateMap<StatusLevelDTO, StatusLevel>()
.ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null));
The solution here works for my project, which is using AutoMapper 6.0.2. In previous projects using AutoMapper 4, I had used IsSourceValueNull to achieve the same behavior.
I made a small change to the original solution. Instead of checking the type of the property to be mapped, I set the filter in ForAllPropertyMaps to check the type of the source object, so that the custom resolver only applies to maps from that source object. But the filter can be set to anything as needed.
var config = new MapperConfiguration(cfg =>
{
cfg.ForAllPropertyMaps(
pm => pm.TypeMap.SourceType == typeof(<class of source object>),
(pm, c) => c.ResolveUsing<object, object, object, object>(new IgnoreNullResolver(), pm.SourceMember.Name));
});
class IgnoreNullResolver : IMemberValueResolver<object, object, object, object>
{
public object Resolve(object source, object destination, object sourceMember, object destinationMember, ResolutionContext context)
{
return sourceMember ?? destinationMember;
}
}
I inspired from @Sergey Berezovskiy
's answer, and made this configuration for all members of all maps in the main config:
Mapper.Initialize(cfg =>
{
cfg.ForAllMaps((obj, cnfg) => cnfg.ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null)));
}