Giusto, prima di tutto, trattiamo con "Qualsiasi codice che chiami il ctor dovrà essere aggiornato quando verranno aggiunte nuove dipendenze"; Per essere chiari, se stai facendo un'iniezione di dipendenza e hai un codice che chiama new () su un oggetto con dipendenze, stai facendo male .
Il tuo contenitore DI dovrebbe essere in grado di iniettare tutte le dipendenze rilevanti, quindi non devi preoccuparti di cambiare la firma del costruttore, quindi l'argomento in realtà non vale.
Per quanto riguarda l'idea dell'iniezione per-metodo vs. per classe, ci sono due problemi principali con l'iniezione per metodo.
Un problema è che i metodi della tua classe dovrebbero condividere le dipendenze, è un modo per assicurarsi che le tue classi siano separate in modo efficace, se vedi una classe con un gran numero di dipendenze (probabilmente più di 4-5) allora quella classe è un candidato ideale per il refactoring in due classi.
Il prossimo problema è che per "iniettare" le dipendenze, per metodo, dovresti passarle nella chiamata al metodo. Ciò significa che dovrai risolvere le dipendenze prima della chiamata al metodo, quindi probabilmente ti ritroverai con un mucchio di codice come questo:
var someDependency = ServiceLocator.Resolve<ISomeDependency>();
var something = classBeingInjected.DoStuff(someDependency);
Ora, dì che chiamerai questo metodo in 10 punti intorno alla tua applicazione: avrai 10 di questi frammenti. Quindi, devi aggiungere un'altra dipendenza a DoStuff (): dovrai cambiare lo snippet per 10 volte (o avvolgerlo in un metodo, nel qual caso stai semplicemente replicando manualmente il comportamento DI, che è uno spreco di tempo).
Quindi, ciò che hai fatto in pratica è che le tue classi DI-use sono consapevoli del proprio contenitore DI, che è una idea fondamentalmente cattiva , in quanto porta molto rapidamente a un design goffo che è difficile da mantenere.
Confrontalo con l'iniezione del costruttore; Nell'iniezione del costruttore non sei legato a un particolare contenitore DI, e non sei mai direttamente responsabile dell'adempimento delle dipendenze delle tue classi, quindi la manutenzione è abbastanza priva di problemi.
A me sembra che tu stia cercando di applicare IoC a una classe contenente una serie di metodi di helper non correlati, mentre potresti essere meglio dividere la classe helper in un certo numero di classi di servizio in base all'utilizzo, quindi usare l'helper delegare le chiamate. Questo non è ancora un grande approccio (un helper classificato con metodi che fanno qualcosa di più complesso di quanto non facciano semplicemente gli argomenti che sono passati a loro sono in genere solo classi di servizio mal scritte), ma almeno manterrà il tuo design un po 'più pulito .
(NB Ho già seguito l'approccio che mi stai suggerendo, ed è stata una pessima idea che non ho ripetuto da allora. Ho scoperto che stavo cercando di separare le classi che non dovevano essere separate, e finì con un insieme di interfacce in cui ogni chiamata al metodo richiedeva una selezione quasi fissa di altre interfacce. Era un incubo da mantenere.)