14

Sono in fase di sviluppo in un nuovo progetto ASP.Net MVC e utilizzo questo progetto per accedere a DI. Sono abbastanza sicuro che andrò con Structure Map, ma non è quello che sto chiedendo. Quello che sto cercando di capire è il modo migliore per organizzare la mia soluzione. Sia il progetto di test unitario che il modello ottengono un file di configurazione per mappare le loro dipendenze o esiste una classe per domarli tutti?Qual è il modo migliore per organizzare una soluzione ASP.Net MVC utilizzando l'iniezione delle dipendenze?

Inoltre, ci sono alcune trappole per principianti da evitare prima di andare troppo lontano in questo?

Molte grazie, tutti .....

Aggiornamento Vorrei aggiungere che quando dico "organizzano la soluzione", non mi riferisco al numero di file/cartelle, ecc, ma piuttosto come strutturare le classi che sono coinvolte con DI. In particolare, come gestire il bootstrapper. Riesco a vedere dove il mio fraseggio da parte mia potrebbe causare confusione.

+1

La mia trappola per principianti con StructureMap era eccezioni delle autorizzazioni di sicurezza in Medium Trust. Dovrai esaminare un contenitore DI alternativo se l'app verrà eseguita in ambienti di media affidabilità. –

risposta

2

Per incoraggiare meglio TDD. Hanno due progetti di test e/o namespace X.Unit.Tests & X.Integrations.Tests.

Ho il mio codice DI nel mio progetto principale in una "directory del namespace" (/ Config) ma nei miei test del codice di integrazione, potrei semplicemente chiamare quei registri o eseguire l'override se richiesto nelle mie fixture o configurazioni di base.

E.g.

/Config/ServiceRegistry.cs /Config/RepositoryRegistry.cs /Config/Bootstrapper.cs

In global.asax chiamo Bootstrapper.Init() e questo chiamerà x.AddRegistry (nuova ServiceRegistry ()) e così via.

Nelle prove di unità non è necessario utilizzare DI solo nei test di integrazione. Nei miei test di integrazione, ad es. se sto testando NHibernate attraverso il database, potrei inizializzare SM con RepositoryRegistry in TestSetUp con un metodo helper che contiene semplicemente GetInstance().

Non divido per progetti. Bootstraper e .Domain fino a quando non ho assolutamente bisogno di ... Tre progetti, X, X.UnitTests, X.Integrazione se hai richiesto più spostamenti in seguito. Sono venuto da un fondo/azienda in forza di avere dozzine di progetti che si sentivano sporchi, una prima riduzione, ma non ora, vado a colpire la crescita correndo rapidamente e riorganizzare la struttura delle soluzioni in seguito, se necessario.

10

Se sei l'unico che lavora al progetto, farei il che cosa ha senso per te prima. Non c'è niente di peggio che avere una directory o una struttura di progetto imposta su di te che non si intuisce. La classe BaseController è nella cartella \ Core \ o nella cartella \ Controller \? Personalmente guarderei nel controller ma alcune persone giurano che dovrebbe essere in \ Core \ o \ Bases.

La prima trappola per principianti sta pensando che è possibile organizzare il codice in modo errato e in qualche modo ciò riflette sul successo del progetto. Ho visto progetti in cui 30 file erano in una cartella e altri progetti in cui c'erano 20 cartelle per 30 file.

La seconda trappola per principianti sta dimenticando che rispetto ad altre lingue si ha il vantaggio di fantastici strumenti di navigazione del codice e di refactoring da Visual Studio. Hai anche un compilatore che rende un file errato molto meno doloroso. Se metti qualcosa nel punto "sbagliato", ok, puoi sempre trovarlo e trascinarlo dove deve essere.

Sarò onesto sto lavorando a un progetto in questo momento e non sono nemmeno sicuro di dove risiedono determinate classi nella mia struttura di file. Vai alla definizione/dichiarazione sono scorciatoie da tastiera che uso molto. Perché è solo io che lavoro con il codice questo va bene. Se dovessi aggiungere un altro sviluppatore al progetto, probabilmente pulirò le cose.

Personalmente tendo a mettere le interfacce con i loro tipi di implementazione all'interno della stessa cartella. IPaymentGateway si trova nella stessa cartella di AuthorizeNetGateway e PaypalGateway. Se non riesco a visualizzare tutti i file in quella cartella contemporaneamente nella mia sidebar di Solution Explorer, sposto tutti i file del Gateway in una cartella \ Gateway \.

Con Iniezione di dipendenze aggiunte al mix, ti consiglio di occuparti solo delle esplosioni nello spazio dei nomi. La cosa peggiore che puoi fare è ingombrare i tuoi bootstrapper e i tuoi file con dichiarazioni e alias lunghi.

ForRequestedType<Customer> 

è più pulita

using KevDog.Models 
using Customer=KevDog.Models.Customer 

o

ForRequestedType<KevDog.Models.Customer> 

Un altro modo per evitare questo problema è quello di essere esplicito, quando le tue cose di denominazione: Cliente, CustomerViewModel, CustomerController, CustomerDataRow, CustomerView

Per TDD devi quasi avere due bootstrap da gestire i tuoi tipi concreti. Davvero non vuoi che i tuoi test unitari utilizzino AuthorizeNetGateway: IPaymentGateway, piuttosto StubGateway: IPaymentGateway.

Ora sono nuovo anche in DI, quindi tendo a rendere le cose molto semplici e rispecchiano le esercitazioni e la documentazione di livello 101. Entrare in un'iniezione dinamica basata su una configurazione di build dovrebbe essere usato solo quando una situazione specifica lo richiede e sai esattamente perché lo fai.

Di solito mantengo la struttura di default anche per le app MVC. È più semplice avere il codice nella stessa struttura del 99% di tutti i tutorial e video.

Spero che questo aiuti.

+0

Grazie jfar! Il commento su TDD è davvero il tipo di cose che volevo chiedere. Penso che l'idea di un bootstrapper per ogni progetto sia la strada da percorrere. Uno nel progetto di test unitario e uno nel progetto MVC – KevDog

0

Ecco il mio primo tentativo di risolvere lo stesso problema per me stesso, ma poiché è il mio primo tentativo, spero che le persone possano commentare o criticare quanto spererei che potesse servire come una possibile soluzione per si:

public VatManager() 
: this(new VatManagerRegistry()) { } 

public VatManager(Registry registry) 
: this(new Action<IInitializationExpression>(x => { x.AddRegistry(registry); })) 
    { 
    } 

public VatManager(Action<IInitializationExpression> action) 
    { 
    ObjectFactory.Initialize(action); 
    data = ObjectFactory.GetInstance<IVatManagerData>(); 
    } 

ho tre sovraccarichi costruttore - il costruttore senza parametri di default ha la conoscenza del Registro StructureMap concreta che deve essere creato per l'utilizzo in un contesto produttivo.Gli altri due permettono ad altri codici che istanziano questa classe manager di fornire il proprio (i) Registro (i) StructureMap o azioni in modo tale che possano controllare le iniezioni di dipendenza stesse, come nel caso di un test automatizzato che fornisce mock invece di istanze concrete di quelle dipendenze. Devo aggiungere che questa soluzione non è specifica per un contesto ASP.NET MVC e non richiama alcuna informazione di configurazione dai file * .config.

Problemi correlati