【发布时间】:2019-02-04 07:41:50
【问题描述】:
我的业务逻辑 Pet 类中有一个 Model 类。
在这个类中,我有一个称为 Type (int = 1, 2, 3, ...) 的鉴别器属性
最终的映射必须是特定派生类的Dto。
我使用了 ConstructUsing,但由于它对基类型映射规则有递归,所以它会引发 Stack Overflow 异常。
派生的 Dto 类被正确映射,因为它们没有递归。
也试过 PreserveReferences() 没有运气
using AutoMapper;
using System;
using System.Collections.Generic;
namespace ConsoleAppMapper
{
class Program
{
static void Main(string[] args)
{
var mapper = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Pet, Dto.Pet>()
.PreserveReferences()
.ForMember(dst => dst.Name, opt => opt.MapFrom(src => src.PetName))
.ConstructUsing((src, context) =>
{
switch (src.Type)
{
case 1: return context.Mapper.Map<Pet, Dto.Dog>(src);
case 2: return context.Mapper.Map<Pet, Dto.Cat>(src);
case 3: return context.Mapper.Map<Pet, Dto.Mouse>(src);
default: return context.Mapper.Map<Pet, Dto.Pet>(src);
}
})
;
cfg.CreateMap<Pet, Dto.Dog>();
cfg.CreateMap<Pet, Dto.Cat>();
cfg.CreateMap<Pet, Dto.Mouse>();
}).CreateMapper();
var pets = new List<Pet>
{
new Pet { PetName = "Bob", Type = 1 },
new Pet { PetName = "Tom", Type = 2 },
new Pet { PetName = "Jerry", Type = 3 },
new Pet { PetName = "Duffy", Type = 4 },
};
var dtoList = mapper.Map<IEnumerable<Pet>, IEnumerable<Dto.Pet>>(pets);
}
}
public class Pet
{
public string PetName;
public int Type;
}
}
namespace Dto
{
public class Pet
{
public string Name;
}
public class Dog : Pet
{
}
public class Cat : Pet
{
}
public class Mouse : Pet
{
}
}
更新: 有了这个版本,它似乎可以正常工作
cfg.CreateMap<Pet, Dto.Pet>()
.ForMember(dst => dst.Name, opt => opt.MapFrom(src => src.PetName))
.ConstructUsing((src, context) =>
{
switch (src.Type)
{
case 1: return context.Mapper.Map<Pet, Dto.Dog>(src);
case 2: return context.Mapper.Map<Pet, Dto.Cat>(src);
case 3: return context.Mapper.Map<Pet, Dto.Mouse>(src);
default: return context.Mapper.Map(src, new Dto.Pet { }, context);
}
})
;
cfg.CreateMap<Pet, Dto.Dog>();
cfg.CreateMap<Pet, Dto.Cat>();
cfg.CreateMap<Pet, Dto.Mouse>();
【问题讨论】:
-
似乎 Map 方法重载可以解决问题,但我不确定这是做我想做的事情的正确方法。
default: return context.Mapper.Map(src, new Dto.Pet { }, context); -
是的,您必须手动传递上下文。这已用github.com/AutoMapper/AutoMapper/issues/2937 更改,因此不再需要。尝试MyGet 构建。
-
最新的 myGet 版本将如何解决此问题?我已经尝试了最后一次 MyGet 构建,但这不是重点。它不起作用的是
default: return context.Mapper.Map<Pet, Dto.Pet>(src);。它的工作原理是default: return context.Mapper.Map<Pet, Dto.Pet>(src, new Dto.Pet { }); -
可能只是参考问题?
-
正如我已经说过的,改变的是你不必再显式地传递上下文了。您需要有相同的上下文以避免 SO。
标签: c# inheritance automapper discriminator