AutoMapper can't prevent null source values if

2019-07-22 17:24发布

问题:

The goal here is to ignore null source values, while not requiring the source object to have all the fields the destination object has. Preventing null seems to only work if ALL fields match between objects.

public class ApiStudent {
    public long Id { get; set; }   
    public string Name { get; set; }    
}

public class DomainStudent {
    public long Id { get; set; }
    public string Name { get; set; }
    public long SchoolId { get; set; }
}

When I run the following mapping:

Mapper.CreateMap<ApiStudent, DomainStudent>()   
    .ForAllMembers(opt => opt.Condition(src => !src.IsSourceValueNull));

var api = new ApiStudent();
api.Id = 123;
api.Name = null;

var domain = new DomainStudent();
domain.Id = 123;
domain.Name = "Homer Simpson"; // goal is to prevent this from being written to null

domain = Mapper.Map(api, domain);
// I get an error here saying the SchoolId mapping is missing from ApiStudent

If I remove the ".ForAllMembers(opt => opt.Condition(src => !src.IsSourceValueNull));" from the Mapping definition, I don't get the error, but then the .Name property will be overwritten to null. What am I missing here to get the AutoMapper to skip properties that exist on the destination object but not the source object?

回答1:

This solved it!

https://github.com/AutoMapper/AutoMapper/issues/432

Quoting the article

We just upgraded from 3.0.0 to 3.1.0 and started getting an issue with mappings with the following definition:

.ForAllMembers(o => o.Condition(c => !c.IsSourceValueNull)); This was previously functioning correctly and would not attempt to map properties which did not have a source value. After the upgrade, it seems that Automapper, when faced with a destination member that has no matching source member, will attempt to map from the source type to the destination member. This then throws a mapping exception because there is no mapping definition for the source type to any of the destination property types. Previously, Automapper seemed to rightfully ignore members which did not have a matching source member.

We changed the condition line to:

.ForAllMembers(o => o.Condition(c => c.PropertyMap.SourceMember != null && !c.IsSourceValueNull));