2010-01-24 3 views
18

Je me demandais s'il est possible de mapper plusieurs objets DTO à un seul objet ViewModel en utilisant Automapper? Fondamentalement, j'ai plusieurs objets DTO et voudrais afficher des informations de chacun sur un seul écran dans ASP.NET MVC 2.0. Pour ce faire, je voudrais aplatir les objets DTO (ou une partie de ceux-ci ...) dans le Viewmodel et transmettre ce viewmodel à la vue. Si j'avais un DTO, ce serait facile, mais je n'ai jamais vu ça se faire avec plusieurs. Évidemment, il y a un certain nombre de façons détournées de le faire (en dehors d'automapper), mais c'est l'approche que je voudrais prendre si possible.Est-il possible de mapper plusieurs objets DTO à un seul ViewModel en utilisant Automapper?

+0

vous pouvez avec le ValueInjecter http://valueinjecter.codeplex.com/documentation – Omu

Répondre

7

Vous pouvez créer un DTO composite qui contient deux objets DTO ou plus et mapper le DTO composite sur le modèle de vue de sortie.

+1

C'est ce que nous avons fait, et j'ai trouvé que cela fonctionne mieux. Cet objet de présentation composite a alors tendance à commencer à contenir un comportement etc. relatif aux objets composites. –

+2

J'ai commencé à descendre cette route mais je me suis rendu compte que si je devais mapper manuellement un objet composite avant que je puisse Map <>(), alors qu'est-ce que cette étape supplémentaire m'offre? En suivant cette approche, vous vous assurez que tous vos mappages d'objets sont gérés via AutoMapper, mais vivent à l'exception des mappages manuels aux composites. Je ne suis pas complètement opposé à l'idée, juste sayin ... – tbehunin

+0

D'accord. La solution que vient de publier Gordon Nongkynrih me semble beaucoup plus élégante. –

13
+0

Bien que très tard dans ce fil ;-), merci beaucoup pour ce lien. Je commence juste avec AutoMapper et j'aurais rencontré ce problème très bientôt! Upvote! :-) –

+0

Merci. Je savais que c'était assez tard dans le fil, mais ayant fait face au même problème récemment. Je me rends compte qu'il n'est jamais trop tard pour mettre à jour même le vieux fil :) – Bahdeng

+5

Je suppose qu'il n'a pas été archivé depuis longtemps ... Plus disponible ... – KDT

4

Vous pouvez ajouter une méthode d'extension de remplacement de la carte de IMappingEngine qui prend un tableau params. Quelque chose comme:

public static class AutoMapperExtensions 
{ 
    public static T Map<T>(this IMappingEngine engine, params object[] sources) where T : class 
    { 
     if (sources == null || sources.Length == 0) 
      return default(T); 

     var destinationType = typeof (T); 
     var result = engine.Map(sources[0], sources[0].GetType(), destinationType) as T; 
     for (int i = 1; i < sources.Length; i++) 
     { 
      engine.Map(sources[i], result, sources[i].GetType(), destinationType); 
     } 

     return result; 
    } 
} 

Vous pouvez alors l'appeler comme ceci:

var result = Mapper.Engine.Map<MyViewModel>(dto1, dto2, dto3); 
7

Si vous avez 2 classes DTO et modèle 1 vue aplanie:

public class Dto1 
{ 
    public string Property1 { get; set; } 
} 
public class Dto2 
{ 
    public string Property2 { get; set; } 
} 
public class FlattenedViewModel 
{ 
    public string Property1 { get; set; } 
    public string Property2 { get; set; } 
} 

Et vous créez les correspondances pour les deux DTO pour voir le modèle:

CreateMap<Dto1, FlattenedViewModel>(); 
CreateMap<Dto2, FlattenedViewModel>(); 

Vous pouvez mapper 1er DTO au modèle et puis juste « ajouter » 2ème DTO:

var dto1 = new Dto1 { Property1 = "Value1"; } 
var dto2 = new Dto2 { Property2 = "Value2"; } 

var model = Mapper.Map<FlattenedViewModel>(dto1); // map dto1 properties 
Mapper.Map(dto2, model); // append dto2 properties 
0

Je viens moi-même travaillé ce et ont une excellente solution. Il est fort probable que vos deux vues sont en fait reliées dans votre système (en particulier si vous utilisez Entity Framework). Vérifiez vos modèles et vous devriez voir quelque chose qui affiche la relation, si vous ne l'ajoutez pas. (Les virtual)

Vos modèles

public class Dto1 
    { 
     public int id { get; set; } 
     public string Property2 { get; set; } 
     public string Property3 { get; set; } 
     public string Property4 { get; set; } 
     public string Property5 { get; set; } 

     public virtual Dto2 dto2{ get; set; } 

    } 

    public class Dto2 
    { 
     public int id { get; set; } 
     public string PropertyB { get; set; } 
     public string PropertyC { get; set; } 
     public string PropertyD { get; set; } 
     public string PropertyE { get; set; } 
    } 

Votre ViewModels

public class Dto1ViewModel 
    { 
     public string Property1 { get; set; } 
     public string Property2 { get; set; } 

     public virtual Dto2VMForDto1 dto2{ get; set; } 
    } 

//Special ViewModel just for sliding into the above 
    public class Dto2VMForDto1 
    { 
     public int id { get; set; } 
     public string PropertyB { get; set; } 
     public string PropertyC { get; set; } 
    } 

Automapper ressemble à ceci:

 cfg.CreateMap< Dto1, Dto1ViewModel>(); 
     cfg.CreateMap< Dto2, Dto2VMForDto1 >(); 

Je suppose que vous obtenez vos données avec LINQ:

Dto1ViewModel thePageVM = (from entry in context.Dto1 where...).ProjectTo<Dto1ViewModel>(); 

Alto, tout va fonctionner. À votre avis, juste l'accès en utilisant model.dto2.PropertyB

Questions connexes