Domanda

Nella maggior parte degli esempi che ho visto sul web, DI nei controller MVC è fatto in questo modo

public ProductController(IProductRepository Rep)
{
    this._rep = Rep;
}

Viene utilizzata una ControllerFactory personalizzata che utilizza il framework DI scelto e il repository viene iniettato.

Perché quanto sopra è considerato migliore di

public ProuctController()
{
    this._rep = ObjectFactory.GetInstance<IProductRepository>();
}

Questo otterrà gli stessi risultati ma non richiede una fabbrica di controller personalizzata.

Per quanto riguarda i test, l'app Test può avere un BootStrapper separato. In questo modo, quando i controller vengono testati, possono ottenere i repository falsi e quando vengono utilizzati per davvero, otterranno quelli reali.

È stato utile?

Soluzione

L'iniezione del costruttore (il primo approccio) è migliore del modello di localizzazione del servizio (il secondo approccio) per diversi motivi.

Innanzitutto, il localizzatore di servizi nasconde le dipendenze. Nel tuo secondo esempio, guardando solo all'interfaccia pubblica, non c'è modo di sapere che ProductControllers necessita di repository.

Inoltre, devo echo OdeToCode . Penso

IProductRepository repository = Mockery.NewMock<IProductRepository>();
IProductController controller = new ProductController(repository);

è più chiaro di

ObjectFactory.SetFactory(IProductRepository, new MockRepositoryFactory())
IProductController controller = new ProductController();

Soprattutto se l'ObjectFactory è configurato nel metodo SetUp di un dispositivo di prova.

Infine, il modello di localizzazione del servizio è evidentemente non ottimale in almeno un caso particolare: quando si scrive codice che verrà utilizzato da persone che scrivono applicazioni al di fuori del proprio controllo. Scommetto che le persone generalmente preferiscono l'iniezione del costruttore (o uno degli altri metodi DI) perché è applicabile per ogni scenario. Perché non utilizzare il metodo che copre tutti i casi?

(Martin Fowler offre un'analisi molto più approfondita in " Inversion of Control Containers and the Dependency Injection Pattern " ; , in particolare la sezione "Localizzatore servizi vs Iniezione dipendenze".

Altri suggerimenti

Lo svantaggio principale per il secondo costruttore è ora che il contenitore IoC deve essere configurato correttamente per ciascun test. Questa configurazione può diventare un vero onere man mano che la base di codice cresce e gli scenari di test diventano più vari. I test sono generalmente più facili da leggere e gestire quando si passa esplicitamente in un doppio test.

Un'altra preoccupazione è l'accoppiamento di un numero enorme di classi a uno specifico framework DI / IoC. Ci sono modi per sottrarlo, ovviamente, ma hai ancora codice disseminato in tutte le classi per recuperare le dipendenze. Dal momento che tutti i buoni framework possono capire quali dipendenze sono necessarie guardando il costruttore, si tratta di uno sforzo sprecato e di un codice duplicato.

Quando si utilizza il secondo approccio, gli svantaggi sono:

  • Sono necessari metodi di installazione / contesto di test enormi e illeggibili
  • Il contenitore è accoppiato al controller
  • Dovrai scrivere molto più codice

Perché vuoi usare comunque un contenitore di ioc quando non vuoi l'iniezione di dipendenza?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top