Sto progettando un nuovo sistema e voglio sapere cos'è l'inversione del controllo (IOC) e, soprattutto, quando usarlo.
Deve essere implementato con le interfacce o può essere fatto con le classi?
Sto progettando un nuovo sistema e voglio sapere cos'è l'inversione del controllo (IOC) e, soprattutto, quando usarlo.
Deve essere implementato con le interfacce o può essere fatto con le classi?
Risposte:
L'IoC (vedere Inversion of Control su Wikipedia) è applicabile nei casi in cui un componente non può eseguire completamente un'attività perché non ha alcune informazioni o funzionalità necessarie.
L'esempio più semplice di un modello IoC sarebbero le funzioni di callback in C. Ad esempio è possibile dichiarare la funzione:
void Iterator(void *list, Func* f)
Che ripete list
sull'applicazione della f
funzione a ciascuno dei suoi elementi. La Iterator
funzione non sa come verrà elaborato ogni elemento, basta fornire una funzione come argomento e li elabora.
Come mostra l'esempio precedente, IoC ti consente di disaccoppiare il tuo programma in componenti separati che non si conoscono. Una delle versioni più comuni di IoC è Dependecy Injection .
In Dependency Injection ogni componente deve dichiarare un elenco di dipendenze richieste per eseguire la propria attività. In fase di esecuzione un componente speciale (generalmente) chiamato contenitore IoC esegue l'associazione tra questi componenti. Cerca di fornire valori per le dipendenze dei componenti pubblicati.
Ecco un esempio in pseudo-codice:
class Foo
{
<Require Boo>Constructor(Boo boo){ boo.DoSomething }
}
In questo esempio la classe Foo
ha un costruttore che richiede un argomento di tipo Boo
per eseguire alcune azioni.
È possibile creare un'istanza di classe Foo
utilizzando un codice simile al seguente:
MyContainer.Create(typeof Foo)
MyContainer
- è un contenitore IoC , che si occupa di ottenere l'istanza Boo
e passarlo al Foo
costruttore.
In breve, IoC ti consente di disaccoppiare il tuo programma in parti separate. Questo va bene perché:
Tuttavia, in alcuni casi, l' IoC può rendere il codice più difficile da comprendere.
Se vuoi vedere un buon esempio di utilizzo del mondo reale di IoC , dai un'occhiata a Mircosoft Composite UI Application Block e CompositeWPF
Spero che la mia spiegazione ti aiuti.
Saluti,
Aku
Da quando ho approfondito questo argomento di recente e ho conservato tutti i segnalibri, il seguente ho trovato prezioso per l'apprendimento di IOC / DI.
Martin Fowlers Articolo originale su IOC / DI
Alcuni concetti da sapere prima
Un'eccellente raccolta di tutorial IOC / DI
Prenota su IOC / DI da Manning Press
Fonte e spiegazione di come creare il proprio COI - Cause La lettura del codice sorgente è sempre il modo migliore per comprendere un concetto.
Ehi JMS, fondamentalmente IoC / DI ti permetterà di definire quale implementazione stai usando una volta, e mantenere una copia statica del tuo contenitore a cui fare riferimento ogni volta che vuoi fare riferimento a esso.
Probabilmente Wikipedia ti aiuterà, ma volevo fare riferimento alla tua seconda parte: sì, l'iniezione di dipendenza può essere fatta per le classi (cioè ogni volta che questo tipo di classe deve essere passato a un metodo, usa questa classe), ma è meglio utilizzare le interfacce, perché in questo modo è possibile modificare la versione di un provider, repository, ecc. che si sta utilizzando semplicemente facendo riferimento alla configurazione.
Ad esempio, supponiamo che tu abbia un'interfaccia per leggere un flusso e che tu abbia avuto un'implementazione XMLStreamReader e SQLStreamReader. Quindi puoi passare il riferimento all'interfaccia ai tuoi metodi e quindi nel tuo contenitore IoC dirgli quale usare.
Quindi, potresti avere ReadPeople (Lettore IStreamReader) pubblico e nella tua configurazione per il tuo contenitore IoC dirlo, ogni volta che ti aspetti che un IStreamReader usi SQLStreamReader.
Quindi, se cambi idea in un secondo momento, devi solo cambiarlo in un unico posto (l'installazione del tuo contenitore) e non importa quanti metodi richiedono un IStreamReader, otterrà sempre l'impostazione predefinita a cui hai detto al tuo contenitore servire.
Supponiamo che tu abbia un validatore per verificare se un'azienda è valida nel tuo sistema. Il tuo "BusinessValidator" può avere un campo di tipo AddressValidator che convalida l'indirizzo parte dell'azienda. Se si desidera testare BusinessValidator senza eseguire il codice esterno (ovvero il codice addressValidator), se si è utilizzato una sorta di IoC / DI nel proprio framework, è possibile "iniettare" un indirizzo falso Validator al suo posto e non doversi preoccupare di testare codice al di fuori dell'ambito della classe in esame.