简体   繁体   中英

AutoMapper does not ignore List when mapping from source to existing destination

I'm having a small problem with AutoMapper. I have isolated the issue I am facing, if it actually is an issue and not just a misunderstanding.

Here are the classes I am working with:

public class DemoEntity
{
    public List<string> Items { get; set; }
    public string Name { get; set; }
}

public class DemoDto
{
    public List<string> Items { get; set; }
    public string Name { get; set; }
}

public class DemoProfile : Profile
{
    public DemoProfile()
    {
        CreateMap<DemoDto, DemoEntity>()
            .ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null));
    }
}

In the Dependency Injection part (which seems to be in Program.cs for .NET 6, but is in Startup.cs in my main project), I have this code which I have read that should help allow nullable collections:

builder.Services.AddAutoMapper(configAction => { configAction.AllowNullCollections = true; }, typeof(Program));

Here is my test-code:

var dto = new DemoDto();
var entity = new DemoEntity()
{
    Items = new List<string>() { "Some existing item" },
    Name = "Existing name"
};

// Works as expected
var newEntity = _mapper.Map<DemoEntity>(dto);

// Sets the entity.Items to an empty list
_mapper.Map(dto, entity);

As you can see in the DemoProfile constructor, I set a condition to only map if srcMember != null , which works for the Name property. With the AllowNullCollections in the service registration, I can map to a new object with a null list (would be an empty list without the AllowNullCollections part).

My expected outcome would be AutoMapper to see that dto.Items is null, and not touch the entity.Items property during the mapping, and leave it with 1 string in the list. The actual outcome is that entity.Items is a list with 0 items. Name property is ignored.

Am I missing something? How can I adjust my code to work so that AutoMapper ignores a list that is null during mapping on an existing destination?

You can look for PreCondition to prevent the mapping from source when the source's member (with the array, List) is null or empty.

CreateMap<DemoDto, DemoEntity>() 
    .ForMember(dest => dest.Items, opt => opt.PreCondition((source, dest) => 
    {
        return source.Items != null && source.Items.Count > 0;
    }))
    .ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null));

Sample demo on .NET Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM