2012-04-30 6 views
0

Dans certains cas, il est nécessaire de renvoyer des DTO composites à partir de notre référentiel, où le DTO a juste quelques propriétés qui sont des propriétés du modèle et la fonction du DTO est juste d'être un simple objet composite (retour d'un Queryable ne suffit pas car il n'y a plus d'informations que T)Automapper DTO composite à la conversion ViewModel

Par exemple:

Modèle:

public class Job 
{ 
    int Id { get; set; } 
    //more properties 
} 

public class JobApplication 
{ 
    int Id { get; set; } 
    //more properties 
} 

Repository: IQueryable<JobAndUserApplication> GetJobAndMatchingUserApplication(int userId):

public class JobAndUserApplication 
{ 
    public Job Job { get; set; } 
    public JobApplication JobApplication { get; set; } 
} 

maintenant - Id comme simplement le faire (projet et sont des fonctionnalités Automapper):

//this allows one efficient query to bring in the subproperties of the composite DTO  
var jobVmList = jobRepository.GetAllJobsAndMatchingJobApplicationByUser(userId)    
          .Project() 
          .To<JobVM>() 
          .ToList(); 

donc je besoin d'une sorte de cartographie comme ceci:

Mapper.CreateMap<JobAndUserApplication, JobVM>() 
     .ForMember(jvm => jvm, opt => opt.ResolveUsing(src => src.Job)); 
     //many other .ForMembers that are not relevant right now 

Je tentais pour mapper la propriété Job du DTO directement sur JobVM (qui partage plusieurs des mêmes propriétés).

Ma cartographie jette l'exception suivante:

configuration personnalisée pour les membres est pris en charge pour les membres individuels de haut niveau sur un type.

Qu'est-ce que je fais de mal et comment puis-je accomplir le mappage de la propriété Job du DTO sur le JobVM lui-même?

Merci

Répondre

1

Automapper vous dit que vous ne pouvez définir des actions personnalisées sur un membre (propriété) d'une classe, non pas sur la classe elle-même. Ce que vous devez faire est de créer d'abord un emploi à la carte JobVM:

Mapper.CreateMap<Job, JobVM>() 

et

Mapper.CreateMap<JobAndUserApplication, JobVM>() 

étant sûr d'ignorer et définir les propriétés en double sur les deux types. Ensuite, exécutez automapper deux fois, d'abord de l'objet enfant:

var jobVM = Mapper.Map<Job, JobVM>(jobAndUserApplication.job); 

puis de l'objet parent

Mapper.Map<JobAndUserApplication, JobVM>(jobAndUserApplication, jobVM); 

Ou l'inverse, selon la façon dont les propriétés sont disposées.

Note de côté rapide: J'ai l'impression que vous êtes en train de mélanger des problèmes, et que mon alarme de code se déclenche. Je voudrais jeter un second regard sur votre modèle viewmodel ou domaine, car ce n'est pas un problème typique que je vois venir. (seulement mes 0,02 $ :-)

+0

Merci Jason. J'essayais d'éviter d'appeler la méthode Map deux fois - pas que ce soit une grosse affaire mais je pensais qu'AutoMapper avec sa riche configuration devrait sûrement pouvoir me permettre de configurer le mapping de telle sorte que je n'ai besoin d'appeler Map qu'une seule fois. Je vais répondre à l'odeur du code dans un commentaire différent. – t316

+0

Nos référentiels ne renvoient que des modèles et nos couches de services fonctionnent sur les référentiels et retournent les DTO.L'appel de plusieurs méthodes de référentiel dans les services pour assembler les résultats renvoyés est un problème de performance inutile (plusieurs requêtes et un traitement en mémoire inutile qu'une base de données fait bien). Il n'y a pas d'autre moyen que d'utiliser une classe composite (qui colle juste deux modèles ensemble) pour renvoyer des modèles afin d'exécuter une seule requête efficace de sélection qui n'a pas à faire dans le traitement de la mémoire. C'est parce que AFAIK Automapper ne peut pas traiter les types anonymes. – t316

+0

Ah c'est logique. Une autre approche que vous pouvez prendre est de configurer la logique de mappage personnalisée est en .AfterMap() Vous utilisez des fonctions anonymes pour définir la logique de mappage personnalisé qui peut vous aider à éviter le second appel. –

Questions connexes