2011-11-15 15 views
7

Mi piacerebbe sapere qual è la migliore pratica nella progettazione dei costruttori di oggetti DTO.C# Dto constructor e dependency injection

dire che ho un oggetto Dto come questo:

class CustomerDto 
{ 
    public string Name { get; set; } 
    public string Surname { get; set; } 
    public string Phone { get; set; } 
    ... 
} 

Ci sono diversi modi per costruire l'oggetto:

ho potuto dichiarare un costruttore:

public CustomerDto(string name, string surname, string phone, ...) 
{ 
    this.Name = name; 
    this.Surname = surname; 
    this.Phone = phone; 
    ... 
} 

Quando si vede questo costruttore e concludere immediatamente una violazione SRP (Responsabilità singola)?

Anche se questi attributi sono tutti correlati.

Si potrebbe anche obiettare v'è alcuna necessità di convalidare le proprietà come questo è un DTO e non ha il comportamento e il comportamento dovrebbe essere piuttosto sull'oggetto dominio che questo le mappe da.

In C# si può anche più elegante costruire questo oggetto:

var dto = new CustomerDto() 
{ 
    Name = "Some name", 
    Surname = "Some surname" 
} 

Oppure utilizzare un costruttore fluente o di un quadro, come NBuilder.

C'è anche l'uso di framework Auto mapping come Automapper. Il problema sta anche usando un contenitore Ioc che il Ctor diventa complesso, così come il rischio nello scambio di argomenti, ad esempio, si passa in nome dove è il cognome o viceversa, la convalida potrebbe perdere questa mappatura più facile quindi esplicita come sopra.

Si prega di aiutare a convincermi che è il modo migliore.

+0

possibile duplicato di [Dipendenza iniezione: utilizzo con oggetti Data Transfer (DTO)?] (Http: // stackoverflow.it/questions/6297322/dependency-injection-use-with-data-transfer-objects-dtos) –

+0

Mi sono imbattuto in questo stesso problema e ho deciso contro il costruttore .. Per una semplice ragione: più tardi, in un mese o 6 mesi, io o qualcun altro lo vedremo e dovremo pensarci allo stesso modo in cui io stesso (e te stesso) stiamo pensando ora. Ho trovato il pensiero mentre leggevo il codice è un'indicazione che è troppo complicato. – dferraro

risposta

10

I tipi di valore come nei tuoi esempi non sono dipendenze. Una dipendenza fornisce una funzionalità (o configurazione) al consumatore. Nel tuo caso sono solo valori normali assegnati al tuo DTO. Finché i dati appartengono insieme non si viola SRP anche se si assegnano molti valori nel costruttore. La sola responsabilità in questo caso è quella di conservare i dati.

Anche i DTO non devono essere creati da un contenitore IoC e non hanno reali dipendenze. Dovresti crearli manualmente, dal tuo framework di persistenza o usando la mappatura automatica.

Se l'assegnazione dei valori utilizzando un costruttore o proprietà è migliore dipende dall'utilizzo. Se sono richiesti, la variante del costruttore è migliore. Se sono facoltativi, la proprietà è migliore.

+0

Ciò che mi piace di questa risposta è che conferma ciò che penso di una dipendenza e che queste non dipendenze reali non sono sottosistemi esterni che si desidera sostituire con un contenitore Ioc. Anche il motivo dell'opzione 2 è che permette davvero al framework Auto mapping di fare le sue cose semplicemente portando i dati tra i confini. Ho sentito che la preoccupazione della Dto che richiede di dire un argomento di nome non è qualcosa di cui è veramente preoccupata? essere d'accordo? – Andre

3

Suggerirei di utilizzare strutture dati immutabili in modo che l'entità DTO non esponga alcun setter, ovviamente in questo modo il costruttore dovrebbe fornire la capacità di inizializzare tutte le proprietà sottostanti di un dato DTO.

quindi preferisco:

public CustomerDto(string name, string surname, string phone, ...) 

DTO è un oggetto di trasferimento dei dati, in particolare per rappresentare un insieme di proprietà per essere passato attraverso un sistema (distribuito pure) confini, quindi non preoccupatevi troppo per quanto riguarda SRP violazione. Questo è come il modello di progettazione della facciata, elimina una serie di operazioni/servizi per semplificare l'utilizzo. Quindi in questo kase Keep It Simple vinto.

+1

Quello che mi sto chiedendo è che Martin Fowler descrive l'oggetto del trasnfer di dati come un oggetto che contiene lo stato e nessun comportamento e in realtà lo considera un modo per ridurre le chiamate di metodo. Introducendo gli argomenti del costruttore e confermandoli si aggiunge il comportamento. Tenere presente che lo scopo è mappare dal dominio alla vista e la convalida avviene molto probabilmente sull'oggetto dominio. Quindi il dto ha davvero bisogno di preoccuparsi degli argomenti e di ciò che è necessario in quanto sta semplicemente trasportando i dati da qualche altra parte e la validazione è una preoccupazione diversa? – Andre

+1

La convalida degli argomenti come 'not null' /' not empty' non è un comportamento di un oggetto, lo consideriamo come il vostro servizio di applicazione. Ma se si intende incapsulare la convalida come 'if (customerRole == Roles.Vip) IncreaseBonus (x)' - questo sarebbe effettivamente un comportamento e non dovrebbe essere presente nel DTO stesso, DTO rappresenta un SALE FINALE di un oggetto – sll

+0

Ho appena provato e sembra che Automapper sia DAVVERO intelligente, mapperà i nomi degli argomenti del costruttore alle proprietà. Il fatto è che mi sembra che dipenda dall'utilizzo, se si esegue il mapping da un oggetto dominio (già validato) a una vista (che convalida) non c'è motivo per creare gli argomenti del costruttore, sembra che l'approccio del costruttore abbia senza aspetti negativi, ma posso vedere uno grande. Non puoi individuare immediatamente se un argomento è il modo sbagliato, o in effetti a quale proprietà è associato un argomento? – Andre

Problemi correlati