Iniezione delle dipendenze con dati di runtime

1

Supponiamo di avere un servizio che deve essere inizializzato, ma poi è singleton . Ad esempio, qualcosa di simile:

public interface IGraphsContainer
{
    void Initialize(IEnumerable<Graph> initialContent);

    void Add(Graph graph);

    bool Contains(Graph graph);

    IEnumerable<Graph> FindAll(Criteria complexCriteria);
}

Supponiamo che l'implementazione non abbia dipendenze. Quindi può essere facilmente associato in un contenitore DI e auto-iniettato in classi che ne hanno bisogno.

Questo funziona per me, aspetto che non debba dimenticare di inizializzare il contenitore prima di usarlo. Ha bisogno di un codice aggiuntivo per impedirlo. Ecco perché non sono felicemente soddisfatto.

C'è una soluzione migliore per questo che non richiede il metodo Initialize?

EDIT: non ero chiaro riguardo al singletion. Il fatto è che è un singleton nel suo ambito, che NON è l'ambito dell'applicazione. Quindi questo metodo di inizializzazione è invocato in qualche altro AbstractFactory.

In questo caso, se i Grafici vengono estratti da una cartella e un utente decide di cambiare la cartella, allora dobbiamo cambiare i grafici in base a quella cartella e quindi il contenuto iniziale dei contenitori.

Ecco il vero esempio in cui sto usando questo approccio Initialize. L'algoritmo sottostante è piuttosto complesso e questo è solo metà di esso. Finora ho bisogno di 3 cose da inizializzare in questo modo.

    
posta Patrik Bak 30.11.2017 - 22:46
fonte

1 risposta

2

Is there a better solution for this that doesn't require the Initialize method?

Vedo due possibili design:

1 .. initialContent dovrebbe passare al costruttore di impl e dovrebbe essere iniettato come dipendenza. Non dovresti rendere Initialize parte di IGraphsContainer a meno che non ci si aspetti che i clienti lo chiamino. Mi piace così:

public interface IGraphsContainer
{
    void Add(Graph graph);
    bool Contains(Graph graph);
    IEnumerable<Graph> FindAll(Criteria complexCriteria);
}

public class DefaultGraphsContainer : IGraphsContainer
{
    public DefaultGraphsContainer(IEnumerable<Graph> initialContent)
    {
        // ...
    }
}

2 .. Se si prevede che i client chiamino Initialize , ti consiglio di estrarre Initialize nella sua interfaccia come abstract fabbrica. È quindi possibile iniettare IGraphsContainerFactory o IGraphsContainer a seconda che il client debba chiamare Create (in precedenza Initialize ) oppure no. Mi piace così:

public interface IGraphsContainerFactory
{
    IGraphsContainer Create(IEnumerable<Graph> initialContent);
}

public interface IGraphsContainer
{
    void Add(Graph graph);
    bool Contains(Graph graph);
    IEnumerable<Graph> FindAll(Criteria complexCriteria);
}
    
risposta data 30.11.2017 - 22:59
fonte

Leggi altre domande sui tag