简体   繁体   中英

Nested Collections Not Working in AutoMapper 5.1

Trying to upgrade to AutoMapper 5.1 from v4.2 and am finding that a collection isn't mapping at runtime - the source object has items in the collection, but the mapped destination property is empty.

Under 4.2, everything worked exactly as expected with the same mapping configuration (save for the MemberList.None in the CreateMap() ctor)

I have DTOs like so

public class GeographicEntity
{
 ...
}

public class County : GeographicEntity
{
    ...
}

public class State : GeographicEntity
{
    public List<County> Counties { get; } = new List<County>();
}

And viewmodels like so

public class GeographicEntityViewModel
{
  ...
}

public class CountyViewModel : GeographicEntityViewModel
{
  ...
}

public class StateViewModel : GeographicEntityViewModel
{
    public List<CountyViewModel> Counties { get; } = new List<CountyViewModel>();
}

And Mapping confirmation like so

Mapper.Initialize(configuration =>
{
  configuration.CreateMap<GeographicEntity, GeographicEntityViewModel>(MemberList.None);

  configuration.CreateMap<County, CountyViewModel>(MemberList.None)
    .IncludeBase<GeographicEntity, GeographicEntityViewModel>();

  configuration.CreateMap<State, StateViewModel>(MemberList.None)
    .IncludeBase<GeographicEntity, GeographicEntityViewModel>();
});

After the Mapper.Map<> call, the Counties collection of the StateViewModel is empty (a list with 0 items) even though the source object has items in its .Counties collection:

var st = new State()
... (initialize the state, including the .Counties list)
var stateViewModel = Mapper.Map<StateViewModel>(st);

Any clues would be appreciated!

After some digging, it turns out that the AutoMapper 5 upgrade introduced some breaking changes. Specifically, the behavior has changed in cases like mine where the destination collection has a getter but no setter. In AutoMapper 4, the default behavior was to use the destination property by default, rather than trying to create a new instance. AutoMapper 5 does NOT do that by default.

The solution is to tell AutoMapper to use the destination value explicitly:

.ForMember(dest => dest.Counties, o => o.UseDestinationValue())

I'm sure there's a good reason for introducing a breaking change like this, but it causes no end of heartache when you've implemented a broad pattern and now have to hunt down and fix every mapped object that might be affected by this change.

I'm almost tempted to just bail on the upgrade and stick with Automapper 4.2, as it did exactly what I needed it to without a lot of extra and unnecessary configuration required.

For more detail, refer to https://github.com/AutoMapper/AutoMapper/issues/1599

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