2010-05-23 21 views
10

Uso frequentemente AutoMapper per mappare oggetti Model (Dominio) su oggetti ViewModel, che vengono quindi utilizzati dalle mie viste, in un modello/modello Vista/Modello di vista.Dove dovrebbero andare le dichiarazioni 'CreateMap'?

Questo implica molte istruzioni 'Mapper.CreateMap', che devono essere tutte eseguite, ma devono essere eseguite solo una volta nel ciclo di vita dell'applicazione.

Tecnicamente, quindi, dovrei tenerli tutti in un metodo statico da qualche parte, che viene chiamato dal mio metodo Application_Start() (questa è un'applicazione ASP.NET MVC).

Tuttavia, sembra sbagliato raggruppare un sacco di problemi di mappatura in un unico punto centrale.

Specialmente quando la mappatura del codice diventa complessa e implica formattazione e altra logica.

C'è un modo migliore per organizzare il codice di mappatura in modo che sia tenuto vicino al ViewModel che interessa?

(mi è venuta un'idea - con un metodo di 'CreateMappings' su ogni ViewModel, e nel BaseViewModel, chiamando questo metodo su instantiation Tuttavia, dal momento che il metodo deve essere chiamato solo volta nel ciclo di vita dell'applicazione,. ha bisogno di una logica aggiuntiva per memorizzare nella cache un elenco di tipi ViewModel per cui è stato chiamato il metodo CreateMappings e quindi chiamarlo solo quando necessario, per ViewModels che non si trovano nell'elenco.)

risposta

2

Se si utilizzano i profili, si può mettere tutte le chiamate "CreateMap" lì. Inoltre, è possibile creare una classe bootstrapper statica che contiene la configurazione e fare in modo che il pezzo di avvio chiami semplicemente il bootstrapper.

+0

Ma che ancora non risolve il problema di avere tutte le mappature per tutti i diversi modelli di view-concentrati insieme, quando avrei preferito in qualche modo legati alle classi a cui si applicano. – Jonathan

0

OK, il modo in cui sto facendo attualmente è questa:

aggiungo un po 'di logica al costruttore della mia BaseController, che gestisce il metodo delle 'CreateMappings', ma solo una volta per Tipo di controller:

public abstract class BaseController : Controller 
{  
    public BaseController() 
    { 
     if (!controllersWithMappingsCreated.Contains(GetType())) 
     { 
      CreateMappings(); 
      controllersWithMappingsCreated.Enqueue(GetType()); 
     } 
    } 

    protected virtual void CreateMappings() { } 
} 

In ogni controller di calcestruzzo, utilizzo CreateMappings per dichiarare i mapping per tutti i Modelli/ViewModel rilevanti per quel controller.

public class AccountController : BaseController 
{ 
    public AccountController() : base() { } 

    protected override void CreateMappings() 
    { 
     Mapper.CreateMap<Models.User, ViewModels.UserProfile>(); 
     Mapper.CreateMap<Models.User, ViewModels.ChangePassword>(); 
    } 
} 

Ho anche trovato alcune alternative interessanti che coinvolgono Attributi here e here, tuttavia essi mi colpiscono come un po 'troppo complicata.

+2

Avrei ancora una classe bootstrapper statica, quindi è possibile annullare la mappatura. – Martin

+0

Bel lavoro. Ma cosa si intende per 'controllersWithMappingsCreated' nel' BaseController'? – Blaise

6

Se davvero non si desidera utilizzare un bootstrapper, almeno un costruttore statico è un modo semplice per assicurarsi che CreateMap venga chiamato al massimo una volta. (Con meno fare in giro e più filo a prova di risposta di Jonathon.)

public class AccountController : Controller 
{ 
    static AccountController() 
    { 
     Mapper.CreateMap<Models.User, ViewModels.UserProfile>(); 
     Mapper.CreateMap<Models.User, ViewModels.ChangePassword>(); 
    } 
} 
+0

Non ho avuto fortuna con l'inserimento delle mappature nel costruttore statico. Trovo che devo metterli nel costruttore di istanze. – AaronLS

+0

@AaronLS Oh no. Hai un'eccezione o qualcosa del genere? Quali classi utilizzi per i costruttori e i mapping? –

Problemi correlati