Buone pratiche per implementare i mapper in un'applicazione multilivello

5

Quando si lavora con un'applicazione multilivello molto spesso si esegue un'attività di conversione di oggetti in un livello in oggetti in un altro livello. Ciò potrebbe essere la conversione di oggetti di database in oggetti di dominio, oggetti di servizio in oggetti di dominio, oggetti di dominio in modelli di visualizzazione, ecc.

Ho visto che viene eseguito in diversi modi, tra cui:

  1. Conversione in linea
  2. Creazione di una classe di traduttore con metodi di supporto statici
  3. Uso dei metodi di estensione per semplificare la conversione
  4. Sostituzione degli operatori di cast
  5. Creazione di classi di mapper separe per ogni possibile traduzione
  6. Utilizzo di soluzioni come automapper

Quale sarebbe il modo "corretto" per gestirlo. L'applicazione con cui lavoro attualmente utilizza una classe di mapper separata per ogni possibile traduzione e, sebbene abbia i vantaggi della testabilità, stiamo utilizzando l'iniezione di dipendenza e dobbiamo passare tutti quei mappatori come dipendenze nel costruttore.

Qualcuno ha trovato un modo migliore per farlo?

Aggiorna

Sto usando lo stack .NET qui (EF + Business Layer + MVC)

    
posta Sebastian K 04.02.2013 - 04:07
fonte

3 risposte

1

Non sono sicuro del modo migliore per implementare la mappatura degli oggetti-oggetto, ma potresti preferire fare affidamento su una libreria appositamente creata per risolverlo. Il mio progetto si basa anche sullo stack .NET e su Automapper ( link ) funziona alla grande. È disponibile tramite NuGet.

    
risposta data 06.02.2013 - 01:04
fonte
1

AutoMapper è una soluzione comune per questo, tuttavia preferisco codificare manualmente i mapping. Di solito ho una classe statica con metodi di estensione che esegue la mappatura da e verso DTO.

[DataContract]
class UserDto
{
 [DataMember]
 public string Name { get; set; }

 [DataMember]
 public DateTime BirthDay { get; set; }
}

class User
{
  public string Name { get; private set; }
  public DateTime BirthDay { get; private set; }
}

static class ContractMappings
{
   public static UserDto ToDto(this User user)
   {
     return new UserDto
     {
       Name = user.Name,
       BirthDay = user.BirthDay
     };
   }
}

Ogni progetto ai limiti dell'applicazione avrà una classe ContractMappings che contiene mappature per tutti i contratti associati a quel progetto. Se questa classe diventa troppo grande potrebbe essere un segno che i limiti del progetto non sono validi.

Le mappature con codice a mano consentono un maggiore grado di flessibilità, che può essere sia un vantaggio che uno svantaggio.

Nel caso di ViewModels, solitamente il ViewModel accetta un DTO o un oggetto dominio nel suo costruttore. Se ViewModel viene utilizzato per creare un DTO o aggiornare un oggetto dominio, inserisco il metodo di aggiornamento direttamente nel ViewModel per mantenere il massimo grado di coesione.

    
risposta data 08.02.2013 - 01:56
fonte
0

La risposta è la soluzione che risolve al meglio il tuo dominio problematico. Di seguito è riportata un'altra soluzione che non hai menzionato.

Utilizza lo stesso tipo per tutti i modelli. La maggior parte degli oggetti che stai usando per memorizzare i dati può essere vista come una hashmap o un dizionario. Il nome della proprietà è la chiave e il valore restituito è il valore. Clojure è un eccellente esempio di linguaggio che supporta questa linea di pensiero con l'uso di parole chiave. Le parole chiave sono una parola o una fase che inizia con due punti e può essere utilizzata come identificatore descrittivo. In Clojure, una mappa è una funzione che può prendere una chiave come argomento e restituire il suo valore associato.

(def my-data-model { :name "Joe" :age 25 })
(my-data-model :name) => "Joe"

Se il tuo modello di dominio è simile a questo:

(def domain-model { :id 1 :value "my data" })

Il tuo modello di visualizzazione potrebbe essere la stessa cosa con: chiave id / coppia di valori rimossa. Con questo approccio, tutti i tuoi "modelli" sono dello stesso tipo e non è necessario tradurre tra loro.

    
risposta data 04.02.2013 - 05:27
fonte

Leggi altre domande sui tag