通常,您将Automapper配置为从类型A映射到类型B.我需要使用automapper映射到类型B或类型C,具体取决于类型A中的属性值。我还需要从类型B或类型映射回来C键入A。
到目前为止提出的解决方案是定义两种类型映射(A => B,A => C)并根据鉴别器调用自定义if / switch contruct中的正确映射。映射嵌套类型,此解决方案不起作用,因为将调用优越的映射。
例如,根据动物的AnimalType值,类型Animal被映射到猫或狗。
我还需要从猫或狗的方式回来,这应该很简单,因为在这里我可以定义2个固定的关系(dog => animal,cat => animal)。
可以映射animal =>要么定义狗还是猫?如果是这样,怎么样?
public enum EAnimalType
{
Cat = 1,
Dog = 2
}
public class Animal
{
public EAnimalType AnimalType { get; set; }
public int Age { get; set; }
}
public abstract class AnimalDto
{
public int Age { get; set; }
}
public class CatDto : AnimalDto {}
public class DogDto : AnimalDto {}
答案 0 :(得分:1)
定义基本类型的映射。此映射使用ConstructUsing
通过调用适用的子映射来实例化正确的子DTO。使用AutoMapper 3.0进行测试。
CreateMap<Animal, AnimalDto>()
// create DTO by dispatching to child type mappings
.ConstructUsing((animal, context) => {
switch (animal.AnimalType) {
case EAnimalType.Dog:
return context.Mapper.Map<DogDto>(animal);
case EAnimalType.Cat:
return context.Mapper.Map<CatDto>(animal);
default:
throw new NotSupportedException(
$"Animal Type '{animal.AnimalType}' is not supported."
);
}
})
// map members of base type
.ForMember(dto => dto.Age, o => o.MapFrom(ent => ent.Age));
// mappings for child types, will handle dispatch from base type
CreateMap<Animal, DogDto>()
.ForMember(dto => dto.Age, o => o.Ignore()) // already mapped from base type
.ForMember(dto => dto.DogSpecific, o => o.MapFrom(dog => dog.DogSpecific));
CreateMap<Animal, CatDto>()
.ForMember(dto => dto.Age, o => o.Ignore()); // already mapped from base type
要实现此功能,Animal, DogDto
配置中使用的AutoMapper必须可以访问映射Animal, CatDto
和Animal, AnimalDto
(例如,在同一个AutoMapper配置文件中定义)。
答案 1 :(得分:0)
使用类型转换器,可以从a映射到b或c。这是有效的,因为在类型转换器中我自己定义了映射指令。缺点:手动定义映射,必须更新,例如,将属性添加到类中。
也许存在更好的解决方案?
[TestMethod]
public void VerifyMappingsSecuritiesModule()
{
// Arrange
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Animal, AnimalDto>().ConvertUsing<TypeTypeConverter>();
});
var expectedAge = 10;
var animal = new Animal { Age = expectedAge, AnimalType = EAnimalType.Cat };
// Act
var catDto = Mapper.Map<Animal, AnimalDto>(animal);
// Assert
Assert.IsInstanceOfType(catDto, typeof(CatDto));
Assert.AreEqual(expectedAge, catDto.Age);
}
public class TypeTypeConverter : ITypeConverter<Animal, AnimalDto>
{
public AnimalDto Convert(ResolutionContext context)
{
var animal = (Animal)context.SourceValue;
if (animal.AnimalType == EAnimalType.Cat) { return new CatDto { Age = animal.Age }; }
else { return new DogDto { Age = animal.Age }; }
}
}