C# 根据ob属性值确定要映射到的类型
通常,您将Automapper配置为从类型A映射到类型B。我需要Automapper映射到类型B或类型C,具体取决于类型A中的属性值。我还需要从类型B或类型C映射回类型A 目前提出的解决方案是定义两种类型的映射(A=>B,A=>C),并根据鉴别器在自定义if/switch构造中调用正确的映射。映射嵌套类型时,此解决方案不起作用,因为此时将调用高级映射。 例如,根据动物的AnimalType值,type Animal映射到猫或狗 我还需要从猫或狗返回的方法,这应该很简单,因为在这里我可以定义2个固定的关系(狗=>animal,猫=>animal) 是否可以定义映射动物=>狗或猫?如果是,怎么做C# 根据ob属性值确定要映射到的类型,c#,automapper,C#,Automapper,通常,您将Automapper配置为从类型A映射到类型B。我需要Automapper映射到类型B或类型C,具体取决于类型A中的属性值。我还需要从类型B或类型C映射回类型A 目前提出的解决方案是定义两种类型的映射(A=>B,A=>C),并根据鉴别器在自定义if/switch构造中调用正确的映射。映射嵌套类型时,此解决方案不起作用,因为此时将调用高级映射。 例如,根据动物的AnimalType值,type Animal映射到猫或狗 我还需要从猫或狗返回的方法,这应该很简单,因为在这里我可以定义2个固
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 {}
使用类型转换器,可以从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 }; }
}
}
[TestMethod]
public void VerifyMappingsSecuritiesModule()
{
//安排
Mapper.Initialize(cfg=>
{
CreateMap().ConvertUsing();
});
var expectedAge=10;
var animal=新动物{年龄=预期年龄,动物类型=EAnimalType.Cat};
//表演
var catDto=Mapper.Map(动物);
//断言
IsInstanceOfType(catDto,typeof(catDto));
Assert.AreEqual(预期年龄、catDto.Age);
}
公共类TypeConverter:ITypeConverter
{
要转换的公共动物(ResolutionContext上下文)
{
var animal=(animal)context.SourceValue;
如果(animal.AnimalType==EAnimalType.Cat){返回新的CatDto{Age=animal.Age};}
else{将新狗返回到{Age=animal.Age};}
}
}
在基本类型上定义映射。此映射使用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
CreateMap()
//通过分派到子类型映射来创建DTO
.ConstructUsing((动物、上下文)=>{
开关(动物。动物类型){
案例EAnimalType.Dog:
返回context.Mapper.Map(动物);
案例EAnimalType.Cat:
返回context.Mapper.Map(动物);
违约:
抛出新的NotSupportedException(
$“不支持动物类型{Animal.AnimalType}。”
);
}
})
//映射基类型的成员
.ForMember(dto=>dto.Age,o=>o.MapFrom(ent=>ent.Age));
//子类型的映射将处理来自基类型的分派
CreateMap()
.ForMember(dto=>dto.Age,o=>o.Ignore())//已从基类型映射
.ForMember(dto=>dto.DogSpecific,o=>o.MapFrom(dog=>dog.DogSpecific));
CreateMap()
.ForMember(dto=>dto.Age,o=>o.Ignore());//已从基类型映射
为此,映射
Animal,DogDto
和Animal,CatDto
必须可由Animal,AnimalDto
配置中使用的自动映射器访问(例如,在相同的自动映射器配置文件中定义)。这里的缺点是必须手动映射成员,而不是退回到已定义的映射配置。我想你可以调用Mapper.Map(动物)
而不是新狗{Age=animal.Age}代码>。谢谢。我将使用构造函数。我的单元测试也成功了。次要更改:This:CreateMap().ForMember(dto=>dto.Age,o=>o.Ignore())替换为This:CreateMap().IncludeBase();