2

L'image a un Person et une classe Group avec une relation plusieurs-à-plusieurs. Une personne a une liste de groupes et un groupe a une liste de personnes.Comment faire pour ignorer la propriété de la propriété dans le mappage AutoMapper?

Lors du mappage Person-PersonDTO J'ai un stack overflow exception parce AutoMapper ne peut pas gérer la Person>Groups>Members>Groups>Members> ...

Alors, voici le code exemple:

public class Person 
{ 
    public string Name { get; set; } 
    public List<Group> Groups { get; set; } 
} 

public class Group 
{ 
    public string Name { get; set; } 
    public List<Person> Members { get; set; } 
} 

public class PersonDTO 
{ 
    public string Name { get; set; } 
    public List<GroupDTO> Groups { get; set; } 
} 

public class GroupDTO 
{ 
    public string Name { get; set; } 
    public List<PersonDTO> Members { get; set; } 
} 

Lorsque j'utilise .ForMember dans la création d'un mappeur, le premier mappeur qui est exécuté lance un null reference exception.

Voici le code pour le mappeur:

CreateMap<Person, PersonDTO>() 
    .ForMember(x => x.Groups.Select(y => y.Members), opt => opt.Ignore()) 
    .ReverseMap(); 

CreateMap<Group, GroupDTO>() 
    .ForMember(x => x.Members.Select(y => y.Groups), opt => opt.Ignore()) 
    .ReverseMap(); 

Alors qu'est-ce que je manque ou faire du tort? Lorsque je supprime les méthodes .ForMember, le null reference exception n'est plus levé.

MISE À JOUR: Je veux vraiment insister sur le point principal de ma question est comment ignorer une propriété d'une propriété. Ce code est juste un exemple plutôt simple.

MISE À JOUR 2: Voici comment je l'ai fixé, un grand merci à Lucian-Bargaoanu

CreateMap<Person, PersonDTO>() 
    .ForMember(x => x.Groups.Select(y => y.Members), opt => opt.Ignore()) 
    .PreserveReferences() // This is the solution! 
    .ReverseMap(); 

CreateMap<Group, GroupDTO>() 
    .ForMember(x => x.Members.Select(y => y.Groups), opt => opt.Ignore()) 
    .PreserveReferences() // This is the solution! 
    .ReverseMap(); 

Merci à .PreserveReferences() les références circulaires sont corrigés!

+0

Merci @Esperadoce, mais mon code est un peu moins simple que l'exemple. Je veux vraiment ignorer une ** propriété d'une propriété ** dans AutoMapper. – Mason

+1

oui vous avez raison, je retire mon drapeau! – Esperadoce

+0

Oui @KirillShlenskiy, ils sont en effet des champs, je voulais juste le garder très simple. Je vais mettre à jour ma question. – Mason

Répondre

2
+0

Oui! Oh mon gawd qui l'a réparé! Merci beaucoup! J'espérais que je n'aurais pas besoin d'utiliser beaucoup de code moche, mais wow juste en ajoutant '.PreserveReferences()' le corrige! Merci encore. – Mason

+1

Un lien vers une solution potentielle est toujours le bienvenu, mais veuillez [ajouter un contexte autour du lien] (// meta.stackoverflow.com/a/8259) pour que vos autres utilisateurs aient une idée de ce que c'est et pourquoi c'est là. ** Toujours citer la partie la plus pertinente d'un lien important, dans le cas où le site cible est inaccessible ou se déconnecte définitivement. ** Tenez compte du fait qu'être plus qu'un lien vers un site externe est une raison possible de comment certaines réponses sont-elles supprimées?] (// stackoverflow.com/help/deleted-answers). – kayess

2

Je pense que le problème que vous rencontrez vient de l'hypothèse fausse que les groupes dans PersonDTO.Groups sont les mêmes que GroupDTO - il ne peut pas en être ainsi sans la boucle de dépendance infinie. Le code suivant devrait fonctionner pour vous:

CreateMap<Person, PersonDTO>() 
    .ForMember(x => x.Groups, opt => opt.Ignore()) 
    .ReverseMap() 
    .AfterMap((src, dest) => 
    { 
     dest.Groups = src.Groups.Select(g => new GroupDTO { Name = g.Name }).ToList() 
    }); 

CreateMap<Group, GroupDTO>() 
    .ForMember(x => x.Members, opt => opt.Ignore()) 
    .ReverseMap() 
    .AfterMap((src, dest) => 
    { 
     dest.Members = src.Members.Select(p => new PersonDTO { Name = p.Name }).ToList() 
    }); 

Vous avez besoin essentiellement d'enseigner AutoMapper qu'en cas de propriété PersonDTO.Groups il devrait cartographier les objets GroupDTO différemment.

Mais je pense que votre problème ressemble plus à un problème d'architecture qu'à un code. PersonDTO.Groups ne doit pas être de type GroupDTO - vous êtes ici uniquement intéressé par les groupes auxquels appartient l'utilisateur et non par les autres membres de ses groupes. Vous devriez avoir une plus simple comme le type:

public class PersonGroupDTO 
{ 
    public string Name { get; set; } 
} 

(le nom est à vous bien sûr) seulement identifier le groupe sans passer outre les membres.

+0

Merci pour votre réponse. C'était comme ça que je l'avais essayé, mais ça n'avait pas l'air si propre d'avoir à faire un DTO séparé juste pour résoudre ce problème. J'ai mis à jour ma question avec une solution très simple pour corriger les références circulaires avec automapper. – Mason

+1

Seulement prendre en compte que l'utilisation de PreserveReferences ralentit automapper dans une certaine mesure :) Sauf que tout va bien. – mr100