我已经创建了一个 dotNetFiddle,展示了这里的问题。
这是我尝试做的事情的一个简化示例……假设我有以下接口:
public interface IPerson
{
int Id { get; set; }
}
public interface IModelPerson : IPerson
{
int BeautyCompetitionsWon { get; set; }
}
在实际的实现中,有许多不同类型的人(例如IUglyPerson
等)。这些是实体类型的契约,例如如下:
public class PersonEntity : IPerson
{
public int Id { get; set; }
}
public class ModelPersonEntity : PersonEntity, IModelPerson
{
public int BeautyCompetitionsWon { get; set; }
}
注意: 每种合同类型可能会有多个实现 - 例如,IModelPerson
也可以由 SupermodelEntity
实现。
我们希望将实体类型映射到数据传输对象(DTO),其大致形式如下:
public abstract class PersonDto : IPerson
{
public int Id { get; set; }
public abstract string PersonType { get; }
}
public class ModelPersonDto : PersonDto, IModelPerson
{
public int BeautyCompetitionsWon { get; set; }
public override string PersonType
{
get { return "Model"; }
}
}
因此,我们创建了一个映射:
Mapper.Initialize(config =>
{
config.CreateMap<IPerson, PersonDto>()
.Include<IModelPerson, ModelPersonDto>()
.ConstructUsing((IPerson person) =>
{
if (person is IModelPerson) return new ModelPersonDto();
throw new InvalidOperationException("Unknown person type: " + person.GetType().FullName);
})
;
config.CreateMap<IModelPerson, ModelPersonDto>();
});
所以,我这里有两个问题。
1. 是否有任何方法可以在没有使用ConstructUsing
子句的情况下创建映射?我认为具有更具体版本的CreateMap
应该已经为我们处理了这个问题,但如果我没有ConstructUsing
子句,AutoMapper会告诉我“不能创建抽象类的实例”。
2. 为什么我的子类属性没有被映射?如果我执行以下映射:
var source = new ModelPersonEntity { Id = 100, BeautyCompetitionsWon = 9 };
var target = Mapper.Map<PersonDto>(source);
target.BeautyCompetitionsWon
的期望值为9,但实际值为0。