自动映射器多对一映射配置
本文关键字:映射 配置 多对一 | 更新日期: 2023-09-27 17:58:00
我想将3个不同的类映射到一个DTO中,每个属性在源和目标上都有相同的名称,类如下:
- 用户
- 候选人
- 投资组合
这是DTO,以及我想如何映射我的对象:
public class CandidateTextInfo
{
public string ProfilePicture { get; set; } //-->User
public ObjectId UserId { get; set; } //-->User
public string Name { get; set; } //--> Candidate
public string Headline { get; set; } //--> Candidate
public Gender Gender { get; set; } //--> Candidate
public byte Rating { get; set; } //--> Candidate
public bool IsCompany { get; set; } //--> Candidate
public string[] Tags { get; set; } //--> Portafolio
public string[] Categories { get; set; } //--> Portafolio
public string ExecutiveSummary { get; set; } //--> Portafolio
public HourlyRate HourlyRate{ get; set; } //--> Candidate
}
我一直在寻找SO,我找到了这个解决方案,但我没有得到方法ConstructUsing
那么我该怎么做才能有一个多对一的映射,如果没有任何变通方法的话,这可能吗?
它在很大程度上取决于对象之间的关系。如果对象之间有1:1的关系(例如,如果User
具有属性User.Candidate
和User.Portfolio
),则映射很容易:-
CreateMap<User, CandidateTextInfo>()
.ForMember(d => d.ProfilePicture, o => o.MapFrom(s => s.ProfilePicture)
// ...
.ForMember(d => d.Name, o => o.MapFrom(s => s.Candidate.Name)
// And so on...
如果你没有一对一的映射,你需要自己安排一点:-
public class CandidateTextInfoSource
{
public CandidateTextInfoSource(User user,
Candidate candidate,
Portafolio portafolio)
{
this.User = user;
this.Candidate = candidate;
this.Portafolio = portafolio;
}
public User User { get; set; }
public Candidate Candidate { get; set; }
public Portafolio Portafolio { get; set; }
}
// ...
CreateMap<CandidateTextInfoSource, CandidateTextInfo>()
.ForMember(d => d.ProfilePicture, o => o.MapFrom(s => s.User.ProfilePicture)
// ...
.ForMember(d => d.Name, o => o.MapFrom(s => s.Candidate.Name)
// And so on...
然后,您可以根据对象之间的关系,使用所需的任何方法来创建CandidateTextInfoSource
。例如,如果我假设User
具有集合User.Candidates
,而Candidate
具有属性Candidate.Portfolio
:-
CreateMap<User, IEnuemerable<CandidateTextInfoSource>>()
.ConstructUsing(
x => x.Candidates
.Select(y => Mapper.Map<CandidateTextInfo>(new CandidateTextInfoSource(x, y, y.Portfolio)))
.ToList());
我很感激这个答案来得很晚,但如果您进一步指定对象之间的关系,我可以帮助您创建更具体的映射。
Automapper的ConstructUsing对于从自定义代码构建一个属性非常有用。在你的情况下,这并不是真正的必要。您只需要创建从对象到DTO的映射。然后将每个对象实例映射到同一个DTO实例。
但是,由于Automapper希望定义目标对象的每个属性,以确保完全指定目标,因此需要将源对象中不存在的属性配置为忽略
CreateMap<Candidate, CandidateTextInfo>()
.ForMember(x=> x.ProfilePicture, opt => opt.Ignore())
.ForMember(...
// repeat for all destination properties not existing in source properties
如果这是太多的样板代码,那么就会探索许多关于堆栈溢出的解决方案,其中这一个看起来很有前景:AutoMapper:"忽略其余的"?(看看Robert Schroeder的回答)