Automapper Configuration de plusieurs à une carte
-
21-12-2019 - |
Question
Je souhaite mapper 3 classes différentes en un seul DTO, chaque propriété a le même nom sur la source et la destination, les classes sont les suivantes :
- Utilisateur
- Candidat
- Portefeuille
c'est le DTO et comment je veux mapper mes objets :
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
}
J'ai cherché dans SO et j'ai trouvé cette solution mais je ne comprends pas la méthode ConstruireUtiliser
alors, comment puis-je faire pour avoir un mappage plusieurs à un, est-ce possible, sinon une solution de contournement ?
La solution
La construction de l'automapper est utile pour construire une propriété à partir de code personnalisé.Dans votre cas, ce n'est pas vraiment nécessaire.Vous avez juste besoin de créer les cartes de vos objets à votre DTO.Puis mappez chaque instance d'objet à la même instance DTO.
Cependant, étant donné que FADAPPPER souhaite que chaque propriété de l'objet de destination soit définie afin de garantir que la destination soit complètement spécifiée, vous devez configurer chaque mappage avec les propriétés non existantes dans l'objet source comme ignoré
CreateMap<Candidate, CandidateTextInfo>()
.ForMember(x=> x.ProfilePicture, opt => opt.Ignore())
.ForMember(...
// repeat for all destination properties not existing in source properties
Si tel est trop de code de la chaudron, de nombreuses solutions sont explorées sur le débordement de la pile, parmi lesquels celui-ci a l'air prometteur: Automapper:" ignorer le reste "? (regardez la réponse de Robert Schroeder)
Autres conseils
Cela dépend grandement des relations entre vos objets.Si vous avez une relation 1:1 entre vos objets (par ex.si User
a des propriétés User.Candidate
et User.Portfolio
) alors le mappage est facile :-
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...
Si vous ne disposez pas d'un mappage individuel, vous devez organiser un peu les choses vous-même : -
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...
Vous pouvez ensuite utiliser tous les moyens dont vous avez besoin pour créer votre CandidateTextInfoSource
en fonction de la relation entre vos objets.Par exemple, si je suppose qu'un User
a une collection User.Candidates
, et un Candidate
a une propriété Candidate.Portfolio
:-
CreateMap<User, IEnuemerable<CandidateTextInfoSource>>()
.ConstructUsing(
x => x.Candidates
.Select(y => Mapper.Map<CandidateTextInfo>(new CandidateTextInfoSource(x, y, y.Portfolio)))
.ToList());
J'apprécie que cette réponse soit très tardive, mais si vous précisez davantage la relation entre vos objets, je peux vous aider à créer un mappage plus spécifique.