简体   繁体   English

Automapper多对一地图配置

[英]Automapper Many to one map configuration

I want to map 3 different classes into a single DTO, each property have the same name on the source and the destination, the classes are the following: 我想将3个不同的类映射到单个DTO中,每个属性在源和目标上具有相同的名称,这些类如下:

  • User 用户
  • Candidate 候选人
  • Portfolio 投资组合

this is the DTO and how I want to map my objects: 这是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
    }

I've been looking in SO and I found this solution but I don't get the method ConstructUsing 我一直在寻找SO,但找到了这个解决方案,但没有得到ConstructUsing方法

so how can I do to have a many to one mapping, is that possible, if not any workaround? 因此,如果没有任何解决方法,我应该怎么做多对一映射?

It depends greatly on the relationships between your objects. 这在很大程度上取决于对象之间的关系。 If you have a 1:1 relationship between your objects (eg if User has properties User.Candidate and User.Portfolio ) then the mapping is easy:- 如果您的对象之间具有1:1的关系(例如,如果User具有User.CandidateUser.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...

If you don't have a one-to-one mapping, you need to arrange things a little bit yourself:- 如果没有一对一的映射,则需要自己进行一些安排:

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...

You can then use whatever means you require to create your CandidateTextInfoSource depending on the relationship between your objects. 然后,您可以根据对象之间的关系使用所需的任何方式来创建CandidateTextInfoSource For example, if I assume that a User has a collection User.Candidates , and a Candidate has a property Candidate.Portfolio :- 例如,如果我假设一个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());

I appreciate that this answer is very late, but if you further specify the relationship between your objects, I can help you create a more specific mapping. 我很欣赏这个答案很晚,但是如果您进一步指定对象之间的关系,我可以帮助您创建更具体的映射。

Automapper's ConstructUsing is useful to build one property from custom code. Automapper的ConstructUsing对于从自定义代码构建一个属性很有用。 In your case it is not really necessary. 在您的情况下,这不是真正必要的。 You just need to create the maps from your objects to your DTO. 您只需要创建从对象到DTO的地图。 Then map each object instance to the same DTO instance. 然后将每个对象实例映射到相同的DTO实例。

However since Automapper wants each property of the destination object to be defined in order to ensure that the destination is fully specified you will need to configure each mapping with the properties not existing in the source object as ignored 但是,由于Automapper希望定义目标对象的每个属性,以确保完全指定了目标,因此您将需要使用源对象中不存在的属性来配置每个映射,而将其忽略

CreateMap<Candidate, CandidateTextInfo>()
.ForMember(x=> x.ProfilePicture, opt => opt.Ignore())
.ForMember(... 
// repeat for all destination properties not existing in source properties

If this is too much boilerplate code, many solutions are explored on stack overflow, among which this one looks promising: AutoMapper: "Ignore the rest"? 如果这是过多的样板代码,则会在堆栈溢出中探索许多解决方案,其中一个看起来很有希望: AutoMapper:“忽略其余部分”吗? (look at Robert Schroeder's answer) (看看罗伯特·施罗德的回答)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM