问题
We are mapping domain hierarchy to the Dto hierarchy and used ReverseMap() to simplify mapping back to domain.
Including all the individual derivates into the mapping was pretty annoying. That's why we've tried to use IncludeAllDerived(). That did work good for some time, but after a while we've got strange exceptions:
System.ArgumentException : Cannot create an instance of abstract type Xxx.Base
After some investigations we've found out, that it was due to using the IncludeAllDerived(). As we've changed it to the explicit includes, it was working again.
The question we were asking ourself was "is it a IncludeAllDerived or ReverseMap or cann't Automapper handle abstract base types or whatever".
回答1:
Some further investigations have shown, that it was a combination of IncludeAllDerived and ReverseMap that was an issue. If we repeat IncludeAllDerived after ReverseMap, than it works as expected. The confusing part is, that repeating Include-calls after ReverseMap was not required.
Here is the code for reproduction (Automapper 9.0.0):
public abstract class Base { }
public class Derived: Base { }
public abstract class BaseDto { }
public class DerivedDto: BaseDto { }
[Test]
public void MappingBase_WithReverseMap_AllDerived()
{
var configuration = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Base, BaseDto>()
.IncludeAllDerived()
.ReverseMap()
.IncludeAllDerived(); // doesn't work without repeating IncludeAllDerived() after ReverseMap()
cfg.CreateMap<Derived, DerivedDto>()
.ReverseMap();
});
var mapper = configuration.CreateMapper();
BaseDto derivedDto = new DerivedDto();
var vm = mapper.Map<Base>(derivedDto);
vm.Should().NotBeNull();
vm.Should().BeOfType<Derived>();
}
[Test]
public void MappingBase_WithReverseMap_IncludeBase()
{
var configuration = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Base, BaseDto>()
.Include<Derived, DerivedDto>()
.ReverseMap(); // works without repeating Include() after ReverseMap()
cfg.CreateMap<Derived, DerivedDto>()
.ReverseMap();
});
var mapper = configuration.CreateMapper();
BaseDto derivedDto = new DerivedDto();
var vm = mapper.Map<Base>(derivedDto);
vm.Should().NotBeNull();
vm.Should().BeOfType<Derived>();
}
来源:https://stackoverflow.com/questions/62085856/why-doesnt-automapper-reverse-the-setting-derive-all-inherited