Domanda

Qualcosa che è stato bugging me da quando ho letto una risposta su un altro stackoverflow domanda precisa mi sfugge ora) dove un utente ha dichiarato qualcosa di simile "Se si chiama il Servizio di localizzazione, si sta facendo male."

E ' stato qualcuno con un alta reputazione (in centinaia di migliaia di persone, credo) quindi tendo a pensare che questa persona potrebbe sapere di cosa stanno parlando.Ho usato DI per i miei progetti, da quando ho iniziato a imparare su di esso, e come ben si riguarda i Test di Unità e che cosa non.E ' qualcosa che mi sto abbastanza comodo, e mi pensare Io so quello che sto facendo.

Tuttavia, ci sono un sacco di posti dove sono stato utilizzando il Localizzatore Servizio per risolvere le dipendenze nel mio progetto.Una volta primo esempio viene dalla mia ModelBinder implementazioni.

Esempio di un tipico modello del raccoglitore.

public class FileModelBinder : IModelBinder {
    public object BindModel(ControllerContext controllerContext,
                            ModelBindingContext bindingContext) {
        ValueProviderResult value = bindingContext.ValueProvider.GetValue("id");

        IDataContext db = Services.Current.GetService<IDataContext>();
        return db.Files.SingleOrDefault(i => i.Id == id.AttemptedValue);
    }
}

non una reale attuazione - solo un rapido esempio

Dal momento che il ModelBinder attuazione richiede una nuova istanza quando un Legante è prima richiesto, è impossibile usare la Dependency Injection sul costruttore per questa particolare implementazione.

È in questo modo in molte delle mie classi.Un altro esempio è quello della Scadenza della Cache del processo che esegue un metodo ogni volta che un oggetto cache scade nel mio sito.Ho eseguito un sacco di chiamate al database e che cosa non.Anche lì sto usando un Servizio di vendita per ottenere la necessaria dipendenza.

Un altro problema che ho avuto di recente (che ho postato una domanda qui su) è che tutto il mio controller necessaria un'istanza di IDataContext che ho usato DI for - ma uno metodo di azione necessaria una diversa istanza di IDataContext.Per fortuna Ninject è venuto in soccorso con un nome dipendenza.Tuttavia, si sentiva come un kludge e non una vera soluzione.

Ho pensato io, almeno, capito il concetto di Separazione dei problemi ragionevolmente bene, ma sembra che ci sia qualcosa di fondamentalmente sbagliato con il mio modo di intendere la Dependency Injection e il Servizio Locator il Motivo - e non so cosa sia.

Il modo che ho attualmente a capire - e questo potrebbe essere sbagliata) è che, almeno in MVC, il ControllerFactory cerca un Costruttore per un Controller e chiama il Servizio Locator stesso per ottenere le dipendenze necessarie e poi li passa in.Tuttavia, posso capire che non tutte le classi e che non hanno una Fabbrica per la loro creazione.Così mi sembra che alcuni Service Locator modello è accettabile...ma...

  1. Quando non è accettabile?
  2. Che tipo di modello dovrei essere sullo sguardo fuori per quando devo ripensare a come sto usando il Servizio Locator Modello?
  3. È il mio ModelBinder attuazione di sbagliato?Se è così, di cosa ho bisogno per imparare a risolvere il problema?
  4. In un'altra domanda, lungo le linee di questo utente Mark Seemann consigliato da un Abstract in Fabbrica Come questo si riferisce?

Credo che sia - non riesco a pensare a nessun altro domanda di aiuto la mia comprensione, ma nessuna ulteriore informazione è molto apprezzato.

Capisco che DI potrebbe non essere la risposta a tutto e potrei essere esagerato nel modo di attuazione, tuttavia, sembra funzionare il modo in cui mi aspetto che con i Test di Unità e che cosa non.

Io non sto cercando il codice per risolvere il mio esempio di implementazione - sto cercando di imparare, alla ricerca di una spiegazione per risolvere la mia comprensione imperfetta.

Desidero stackoverflow.com aveva la possibilità di salvare le bozze di domande.Spero anche che chi risponde a questa domanda ottiene la giusta quantità di reputazione per rispondere a questa domanda penso di chiedere molto.Grazie, in anticipo.

È stato utile?

Soluzione

Si consideri il seguente:

public class MyClass
{
  IMyInterface _myInterface;
  IMyOtherInterface _myOtherInterface;

  public MyClass(IMyInterface myInterface, IMyOtherInterface myOtherInterface)
  {
    // Foo

    _myInterface = myInterface;
    _myOtherInterface = myOtherInterface;
  }
}

Con questo disegno sono in grado di esprimere i requisiti di dipendenza per il mio tipo.Il tipo di per sè non è responsabile per sapere come creare un'istanza di una qualsiasi delle dipendenze, sono dato (iniettato), con qualsiasi risoluzione viene utilizzato il meccanismo [in genere un contenitore IoC].Considerando che:

public class MyClass
{
  IMyInterface _myInterface;
  IMyOtherInterface _myOtherInterface;

  public MyClass()
  {
    // Bar

    _myInterface = ServiceLocator.Resolve<IMyInterface>();
    _myOtherInterface = ServiceLocator.Resolve<IMyOtherInterface>();
  }
}

La nostra classe è ora dipende creazione di specifiche istanze, ma tramite delega ad un servizio di localizzazione.In questo senso, la Posizione di Servizio può essere considerato un anti-pattern perché non stai esponendo le dipendenze, ma si consente di problemi che possono essere catturati attraverso la compilazione di bolle in fase di runtime.(Una buona lettura è qui).Si nasconde complessità.

La scelta tra l'uno o l'altro dipende da ciò che il vostro edificio e i servizi che fornisce.In genere se si sta creando un'applicazione da zero, vorrei scegliere DI tutto il tempo.Migliora la gestibilità, favorisce la modularità e la rende tipi di test molto più facile.Ma, ASP.NET MVC3 ad esempio, è possibile implementare facilmente SL come la sua cotta nel design.

Si può sempre andare per un design composito in cui si potrebbe utilizzare IoC/DI con SL, molto simile utilizzando il Comuni Servizi Locator.È componente di ricambio può essere collegato tramite DI, esposto, ma attraverso la SL.Si potrebbe anche buttare composizione in mix e usare qualcosa di simile (Managed Extensibility Framework che supporta DI, ma può anche essere collegato ad altri IoC container o di un servizio locator).E ' una grande scelta di design per rendere, in genere il mio consiglio sarebbe per IoC/DI dove possibile.

Il design specifico non direi che è sbagliato.In questo esempio, il codice non è responsabile per la creazione di un'istanza del modello del raccoglitore di per sé, che il quadro non avete controllo sopra che ma l'utilizzo del servizio locator, probabilmente, potrebbe essere facilmente modificato per accedere a un IoC container. Ma l'azione di chiamata a deliberare sulla IoC container...non si considera che la posizione di servizio?

Con un astratto modello factory la fabbrica è specializzata in creazione di tipi specifici.Non si registra tipi per la risoluzione, è essenzialmente registrare un abstract di fabbrica e che costruisce tutti i tipi che si possono richiedere.Con un Servizio Locator è stato progettato per individuare i servizi e tornare a quelle istanze.Simili, da una convenzione punto di vista, ma molto diversi nel comportamento.

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