Domanda

Ho appena iniziato con i contenitori IoC, quindi mi scuso se questa è una domanda stupida.

Ho un codice simile al seguente in un'app

internal static class StaticDataHandlerFactory
    {
        public static IStaticDataHandler CreateHandler(StaticDataUpdate staticDataUpdate)
        {
            if (staticDataUpdate.Item is StaticDataUpdateOffice)
            {
                return new OfficeUpdateHandler();
            }

            if (staticDataUpdate.Item is StaticDataUpdateEmployee)
            {
                return new EmployeeUpdateHandler();   
            }

            if (staticDataUpdate.Item == null)
            {
                throw new NotImplementedException(
                    string.Format("No static data provided"));
            }
            else
            {
                throw new NotImplementedException(
                    string.Format("Unimplemented static data type of {0}", staticDataUpdate.Item.GetType().FullName));
            }
        }
    }

È fondamentalmente una semplice fabbrica che restituisce la strategia corretta per la gestione dei dati di input.

Un contenitore IoC mi permetterebbe di eliminare codice come questo? Vale a dire: mi consentirebbe di scegliere dinamicamente un'implementazione concreta da caricare in base al tipo di parametro di input?

O sto andando fuori rotta qui?

È stato utile?

Soluzione

In realtà, sebbene sia possibile sostituire parte del codice con un'inversione del sistema di controllo, per me non è ovvio che sia una buona idea. L'iniezione di dipendenza tende ad essere la migliore per la configurazione di sistemi, non per la creazione dinamica di oggetti. Per dirla in modo diverso, il contenitore stesso è un'enorme variabile globale e come tale dovrebbe apparire in gran parte del codice.

A parte questo, il codice sembra violare la Legge di Demetra . Sembra che il parametro debba essere di tipo " StaticDataUpdateItem " anziché " StaticDataUpdate " ;. Con ciò osservato, c'è un argomento piuttosto forte per riscrivere questo codice come una chiamata di metodo su StaticDataUpdateItem.

Ho usato l'IoC piuttosto pesantemente, ma la creazione dinamica di oggetti è ancora meglio gestita usando un modello di fabbrica astratto. In breve, se non ti piace l'idea di aggiungere un metodo all'elemento stesso per generare l'handle, probabilmente è meglio lasciare il codice così com'è.

Altri suggerimenti

Non sei affatto fuori rotta; per come lo capisco, sei abbastanza vicino.

Il modo in cui strutturerei più comunemente questo genere di cose è quello di trasformare la tua classe Factory nel tuo contenitore IoC, semplicemente consentendo agli UpdateHandlers che vengono restituiti di essere specificati usando Dependency Injection. Quindi, invece di avere la logica nel tuo codice che specifica che StaticDataUpdateOffice significa restituire OfficeUpdateHandler, puoi trasformare il tuo codice nel dire semplicemente che StaticDataUpdateOffice restituisce qualunque cosa contenga una variabile (appena specificata) m_officeUpdateHandler ; fintanto che il tuo Framework si assicurerà di impostare il valore di m_officeUpdateHandler prima di invocare la tua fabbrica, sei a posto. E puoi cambiare il valore di m_officeUpdateHandler in qualsiasi cosa tu voglia in fase di esecuzione quando cambiano le tue esigenze.

Questa Iniezione delle dipendenze ti consente di avere il controllo sul processo di inversione del controllo; puoi avere una semplice fabbrica che restituisce i tuoi gestori e puoi astrarre la logica che controlla quale gestore viene restituito in una posizione diversa, come appropriato.

Nota: la mia esperienza con questo genere di cose è piuttosto fortemente guidata dalla mia (molto positiva) esperienza con Spring, e quindi ciò può colorare la mia interpretazione della tua domanda (e la risposta).

La risposta breve è sì, lo consente. Questo post sul blog mostra un modo semplice per scegliere l'implementazione in fase di esecuzione utilizzando Windsor. L'autore, Ayende, elabora qui e qui .

Non l'ho ancora provato, ma mi aspetto di farlo presto.

Sono d'accordo con le altre risposte qui, che sì, puoi farlo in questo modo. Ma perché non usi un generico?

public static IStaticDataHandler CreateHandler<T>( params object[] args )
{...

dove args può essere passato come argomento ctor (ad esempio ad Activator).

Devo ancora leggere qui qualsiasi parola che abbia molto senso.

IoC è più per la configurazione?

La creazione dinamica di oggetti è meglio cosa? Generics? Questo è tutto fuori tema.

1) IoC non è altro che un bel risparmio di tempo rispetto all'implementazione del vangelo 'composizione sulla specializzazione / ereditarietà'.

Quindi la regola n. 1 per l'utilizzo di un IoC è che dovresti essere davvero stanco di dover trattare con costruttori lunghi che seguono il "vincolo al contratto e non l'implementazione".

Detto in altro modo, questo è il modello stratey come alternativa al modello del modello per gli stessi motivi (incapsulare ...) ... MA è più lavoro per creare tutti i tipi di interfaccia / astratta extra ed è più lavorare per farlo OGNI volta con tutto l'IServiceProvicerThis e IResolverThat ... Se non sei stanco di dover adempiere noiosamente ai contratti di codice come:

IInterestingService interesting = ... ottieni comunque un'istanza ..

aggiungi altre tre righe come questa ..

poi

Servizio IAmazementService = nuovo AmazementService (interessante, seconda categoria, terzo, ecc ...)

Che invecchia. Quindi l'IoC non è mai una domanda perché chiunque sia abbastanza intelligente da programmare usando un design solido lo saprebbe meglio. Quelli che chiedono hanno tutte le risposte sbagliate.

Quindi, se davvero si incontra quanto sopra, allora assolutamente. I contenitori IoC sono pronti a fare tutto il lavoro "creativo" di cui puoi trarre vantaggio dal farli gestire. E l'astensione creazionale più comune rispetto al nuovo esplicito è Mr. Factory.

Damon

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